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();
}