diff --git a/httpdocs/js/utils/datatable-utils.js b/httpdocs/js/utils/datatable-utils.js index 3b7890589d..3a9aff50b3 100644 --- a/httpdocs/js/utils/datatable-utils.js +++ b/httpdocs/js/utils/datatable-utils.js @@ -678,11 +678,25 @@ class DataTableRenders { let cliLabel = DataTableRenders.filterize('cli_ip', flow.cli_ip.value, flow.cli_ip.label); let cliPortLabel = ((flow.cli_port && flow.cli_port > 0) ? ":"+DataTableRenders.filterize('cli_port', flow.cli_port, flow.cli_port) : ""); - let cliIcons = (row.is_attacker_to_victim ? "" : ""); let srvLabel = DataTableRenders.filterize('srv_ip', flow.srv_ip.value, flow.srv_ip.label); let srvPortLabel = ((flow.cli_port && flow.cli_port > 0) ? ":"+DataTableRenders.filterize('srv_port', flow.srv_port, flow.srv_port) : ""); - let srvIcons = (row.is_victim_to_attacker ? "" : ""); + + let cliIcons = ""; + let srvIcons = ""; + if (row.cli_role) { + if (row.cli_role.value == 'attacker') + cliIcons += DataTableRenders.filterize('roles', 'has_attacker', '', row.cli_role.label); + else if (row.cli_role.value == 'victim') + cliIcons += DataTableRenders.filterize('roles', 'has_victim', '', row.cli_role.label); + } + + if (row.srv_role) { + if (row.srv_role.value == 'attacker') + srvIcons += DataTableRenders.filterize('roles', 'has_attacker', '', row.srv_role.label); + else if (row.srv_role.value == 'victim') + srvIcons += DataTableRenders.filterize('roles', 'has_victim', '', row.srv_role.label); + } return `${active_ref} ${historical_ref} ${cliLabel}${cliPortLabel} ${cliIcons} ${flow.cli_ip.reference} ${srvLabel}${srvPortLabel} ${srvIcons} ${flow.srv_ip.reference}`; } diff --git a/httpdocs/misc/alert_store_schema.sql b/httpdocs/misc/alert_store_schema.sql index 7b69adf0b2..d06d9ebc92 100644 --- a/httpdocs/misc/alert_store_schema.sql +++ b/httpdocs/misc/alert_store_schema.sql @@ -38,8 +38,10 @@ CREATE TABLE IF NOT EXISTS `flow_alerts` ( `cli_port` INTEGER NOT NULL DEFAULT 0 CHECK(`cli_port` BETWEEN 0 AND 65535), `srv_port` INTEGER NOT NULL DEFAULT 0 CHECK(`srv_port` BETWEEN 0 AND 65535), `vlan_id` INTEGER NOT NULL DEFAULT 0 CHECK(`vlan_id` >= 0), -`is_attacker_to_victim` INTEGER NOT NULL DEFAULT 0 CHECK(`is_attacker_to_victim` IN (0,1)), -`is_victim_to_attacker` INTEGER NOT NULL DEFAULT 0 CHECK(`is_victim_to_attacker` IN (0,1)), +`is_cli_attacker` INTEGER NOT NULL DEFAULT 0 CHECK(`is_cli_attacker` IN (0,1)), +`is_cli_victim` INTEGER NOT NULL DEFAULT 0 CHECK(`is_cli_victim` IN (0,1)), +`is_srv_attacker` INTEGER NOT NULL DEFAULT 0 CHECK(`is_srv_attacker` IN (0,1)), +`is_srv_victim` INTEGER NOT NULL DEFAULT 0 CHECK(`is_srv_victim` IN (0,1)), `proto` INTEGER NOT NULL DEFAULT 0 CHECK(`proto` >= 0), `l7_proto` INTEGER NOT NULL DEFAULT 0 CHECK(`l7_proto` >= 0), `l7_master_proto` INTEGER NOT NULL DEFAULT 0 CHECK(`l7_master_proto` >= 0), diff --git a/httpdocs/templates/pages/alerts/families/flow/table.js.template b/httpdocs/templates/pages/alerts/families/flow/table.js.template index fac18b2b60..e7f36b88cc 100644 --- a/httpdocs/templates/pages/alerts/families/flow/table.js.template +++ b/httpdocs/templates/pages/alerts/families/flow/table.js.template @@ -12,10 +12,6 @@ {responsivePriority: 3, name: 'flow', data: 'flow', orderable: false, className: 'text-nowrap', width: '12%', render: DataTableRenders.formatFlowTuple}, /* Description */ {responsivePriority: 2, name: 'alert', data: 'msg', orderable: false, className: 'text-nowrap', render: DataTableRenders.formatNameDescription }, - /* Attacker */ - {responsivePriority: 3, name: 'is_attacker_to_victim', data: 'is_attacker_to_victim', orderable: true, width: '8%', className: 'text-center'}, - /* Victim */ - {responsivePriority: 3, name: 'is_victim_to_attacker', data: 'is_victim_to_attacker', orderable: true, width: '8%', className: 'text-center'}, /* Counts */ {responsivePriority: 3, name: 'count', className: 'text-center', width: '3%', data: 'count', visible: false}, /* Description */ diff --git a/httpdocs/templates/pages/alerts/families/flow/table.template b/httpdocs/templates/pages/alerts/families/flow/table.template index cbfb9f7bf3..3f9185e1c6 100644 --- a/httpdocs/templates/pages/alerts/families/flow/table.template +++ b/httpdocs/templates/pages/alerts/families/flow/table.template @@ -4,8 +4,6 @@ {{ i18n("protocol") }} {{ i18n("flow") }} {{ i18n("alerts_dashboard.alert") }} - {{ i18n("is_attacker_to_victim") }} - {{ i18n("is_victim_to_attacker") }} {{ i18n("show_alerts.alert_counts") }} {{ i18n("description") }} {{ i18n("flow_details.additional_alert_type") }} diff --git a/httpdocs/templates/pages/modals/alerts/filters/add.template b/httpdocs/templates/pages/modals/alerts/filters/add.template index 6e1f93dff5..2f9d524f84 100644 --- a/httpdocs/templates/pages/modals/alerts/filters/add.template +++ b/httpdocs/templates/pages/modals/alerts/filters/add.template @@ -138,8 +138,9 @@
diff --git a/include/FlowAlert.h b/include/FlowAlert.h index 6784667f85..bd241b4256 100644 --- a/include/FlowAlert.h +++ b/include/FlowAlert.h @@ -29,6 +29,7 @@ class FlowAlert { Flow *flow; std::string callback_name; bool cli_attacker, srv_attacker; + bool cli_victim, srv_victim; /* Adds to the passed `serializer` (generated with `getAlertSerializer`) information specific to this alert @@ -43,7 +44,10 @@ class FlowAlert { inline void setSrvAttacker() { srv_attacker = true; } inline bool isCliAttacker() { return cli_attacker; } + inline bool isCliVictim() { return cli_victim; } + inline bool isSrvAttacker() { return srv_attacker; } + inline bool isSrvVictim() { return srv_victim; } virtual FlowAlertType getAlertType() const = 0; diff --git a/include/ntop_defines.h b/include/ntop_defines.h index cde1081667..636af0bfe1 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -881,7 +881,7 @@ #define STATS_MANAGER_STORE_NAME "top_talkers.db" #define ALERTS_STORE_SCHEMA_FILE_NAME "alert_store_schema.sql" -#define ALERTS_STORE_DB_FILE_NAME "alert_store_v05.db" +#define ALERTS_STORE_DB_FILE_NAME "alert_store_v06.db" #define NTOPNG_DATASOURCE_KEY "ntopng.datasources" #define NTOPNG_DATASOURCE_URL "/datasources/" diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index fc3656afe3..9807b6baa1 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -132,6 +132,8 @@ local lang = { ["geolocation_unavailable"] = "Please follow these instructions .", ["geolocation_unavailable_title"] = "Running without Geolocation support", ["granularity"] = "Granularity", + ["has_attacker"] = "Has Attacker", + ["has_victim"] = "Has Victim", ["hassh_fingerprint"] = "HASSH Fingerprint", ["health"] = "Health", ["help"] = "Help", @@ -161,8 +163,6 @@ local lang = { ["ip_address"] = "IP Address", ["ipv4"] = "IPv4", ["ipv6"] = "IPv6", - ["is_attacker_to_victim"] = "Attacker to Victim", - ["is_victim_to_attacker"] = "Victim to Attacker", ["ja3_client_fingerprint"] = "JA3 Client Fingerprint", ["ja3_fingerprint"] = "JA3 Fingerprint", ["key"] = "Key", @@ -191,6 +191,7 @@ local lang = { ["next"] = "Next", ["no"] = "No", ["noTraffic"] = "No traffic has been reported for the specified date/time selection", + ["no_attacker_nor_victim"] = "No Attacker/Victim", ["no_data_available"] = "No Data Available", ["no_flows"] = "No Flows", ["no_ports"] = "No Ports", @@ -670,8 +671,8 @@ local lang = { ["host_alert_dns_server_contacts"] = "DNS Server Contacts", ["host_alert_ntp_server_contacts"] = "NTP Server Contacts", ["host_alert_smtp_server_contacts"] = "SMTP Server Contacts", - ["host_ban_title"] = "Dangerous Host", ["host_ban_description"] = "Trigger an alert when an host crosses the configured threshold for more than 5 minutes consecutively", + ["host_ban_title"] = "Dangerous Host", ["host_log"] = "Host Log", ["host_pool_connection"] = "Host Pool Connection", ["host_pool_disconnection"] = "Host Pool Disconnection", diff --git a/scripts/lua/modules/alert_store/flow_alert_store.lua b/scripts/lua/modules/alert_store/flow_alert_store.lua index 2daace58e4..7df1b0dd4d 100644 --- a/scripts/lua/modules/alert_store/flow_alert_store.lua +++ b/scripts/lua/modules/alert_store/flow_alert_store.lua @@ -34,11 +34,11 @@ end function flow_alert_store:insert(alert) local insert_stmt = string.format("INSERT INTO %s ".. "(alert_id, tstamp, tstamp_end, severity, cli_ip, srv_ip, cli_port, srv_port, vlan_id, ".. - "is_attacker_to_victim, is_victim_to_attacker, proto, l7_proto, l7_master_proto, l7_cat, ".. + "is_cli_attacker, is_cli_victim, is_srv_attacker, is_srv_victim, proto, l7_proto, l7_master_proto, l7_cat, ".. "cli_name, srv_name, cli_country, srv_country, cli_blacklisted, srv_blacklisted, ".. "cli2srv_bytes, srv2cli_bytes, cli2srv_pkts, srv2cli_pkts, first_seen, community_id, score, ".. "flow_risk_bitmap, alerts_map, json) ".. - "VALUES (%u, %u, %u, %u, '%s', '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', '%s', '%s', ".. + "VALUES (%u, %u, %u, %u, '%s', '%s', %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', '%s', '%s', ".. "'%s', %u, %u, %u, %u, %u, %u, %u, '%s', %u, %u, X'%s', '%s'); ", self._table_name, alert.alert_id, @@ -51,7 +51,9 @@ function flow_alert_store:insert(alert) alert.srv_port, alert.vlan_id, ternary(alert.is_cli_attacker, 1, 0), + ternary(alert.is_cli_victim, 1, 0), ternary(alert.is_srv_attacker, 1, 0), + ternary(alert.is_srv_victim, 1, 0), alert.proto, alert.l7_proto, alert.l7_master_proto, @@ -193,15 +195,17 @@ end -- ############################################## --@brief Add filter on roles ---@param roles The roles (attacker2victim or victim2attacker) +--@param roles The roles (had_attacker, has_victim, no_attacker_nor_victim) --@return True if set is successful, false otherwise function flow_alert_store:add_roles_filter(roles) if not self._roles then self._roles = roles - if roles == 'attacker2victim' then - self._where[#self._where + 1] = "is_attacker_to_victim = 1" - elseif roles == 'victim2attacker' then - self._where[#self._where + 1] = "is_victim_to_attacker = 1" + if roles == 'has_attacker' then + self._where[#self._where + 1] = "(is_cli_attacker = 1 OR is_srv_attacker = 1)" + elseif roles == 'has_victim' then + self._where[#self._where + 1] = "(is_cli_victim = 1 OR is_srv_victim = 1)" + elseif roles == 'no_attacker_nor_victim' then + self._where[#self._where + 1] = "(is_cli_attacker = 0 AND is_srv_attacker = 0 AND is_srv_victim = 0 AND is_cli_victim = 0)" end return true end @@ -454,14 +458,10 @@ function flow_alert_store:format_record(value, no_html) label = l4_protocol } - record["is_attacker_to_victim"] = "" - record["is_victim_to_attacker"] = "" - - if value["is_attacker_to_victim"] == "1" and not no_html then - record["is_attacker_to_victim"] = '' - elseif value["is_victim_to_attacker"] == "1" and not no_html then - record["is_victim_to_attacker"] = '' - end + if value["is_cli_victim"] == "1" then record["cli_role"] = { value = 'victim', label = i18n("victim") } end + if value["is_cli_attacker"] == "1" then record["cli_role"] = { value = 'attacker', label = i18n("attacker") } end + if value["is_srv_victim"] == "1" then record["srv_role"] = { value = 'victim', label = i18n("victim") } end + if value["is_srv_attacker"] == "1" then record["srv_role"] = { value = 'attacker', label = i18n("attacker") } end record["l7_proto"] = { value = value["l7_proto"], diff --git a/scripts/lua/modules/http_lint.lua b/scripts/lua/modules/http_lint.lua index 347e27f292..afbf954e96 100644 --- a/scripts/lua/modules/http_lint.lua +++ b/scripts/lua/modules/http_lint.lua @@ -1514,7 +1514,7 @@ local known_parameters = { ["alert_granularity"] = validateNumber, -- An alert granularity ["entity"] = validateNumber, -- An alert entity type ["role"] = validateFilters(validateSingleWord), -- attacker/victim - ["roles"] = validateFilters(validateSingleWord), -- attacker2victim/victim2attacker + ["roles"] = validateFilters(validateSingleWord), -- has_attacker/has_victim ["asn"] = validateNumber, -- An ASN number ["module"] = validateTopModule, -- A top script module ["step"] = validateNumber, -- A step value diff --git a/src/Flow.cpp b/src/Flow.cpp index 17c88b8beb..47ec3db5ac 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -2742,7 +2742,9 @@ void Flow::alert2JSON(FlowAlert *alert, ndpi_serializer *s) { ndpi_serialize_string_int64(s, "tstamp", now); ndpi_serialize_string_int64(s, "alert_id", alert->getAlertType().id); ndpi_serialize_string_boolean(s, "is_cli_attacker", alert->isCliAttacker()); + ndpi_serialize_string_boolean(s, "is_cli_victim", alert->isCliVictim()); ndpi_serialize_string_boolean(s, "is_srv_attacker", alert->isSrvAttacker()); + ndpi_serialize_string_boolean(s, "is_srv_victim", alert->isSrvVictim()); // alert_entity MUST be in sync with alert_consts.lua flow alert entity ndpi_serialize_string_int32(s, "entity_id", alert_entity_flow); diff --git a/src/FlowAlert.cpp b/src/FlowAlert.cpp index e81991f0b0..2f0160a976 100644 --- a/src/FlowAlert.cpp +++ b/src/FlowAlert.cpp @@ -26,6 +26,7 @@ FlowAlert::FlowAlert(FlowCallback *c, Flow *f) { flow = f; cli_attacker = srv_attacker = false; + cli_victim = srv_victim = false; if (c) callback_name = c->getName(); }