From 08fb295be9ba6f213197d44ea6ce152e71d1f809 Mon Sep 17 00:00:00 2001 From: Simone Mainardi Date: Mon, 31 May 2021 12:32:56 +0200 Subject: [PATCH] Implements support for roles (attacker/victim) filtering of alerts Implements #5425 --- include/AlertableEntity.h | 3 +- include/HostAlertableEntity.h | 3 +- include/NetworkInterface.h | 2 +- include/OtherAlertableEntity.h | 6 ++-- include/ntop_typedefs.h | 11 +++++++ scripts/lua/modules/alert_roles.lua | 30 +++++++++++++++++++ .../lua/modules/alert_store/alert_store.lua | 5 +++- .../modules/alert_store/host_alert_store.lua | 3 ++ src/HostAlertableEntity.cpp | 13 ++++++-- src/LuaEngineInterface.cpp | 6 ++-- src/NetworkInterface.cpp | 6 ++-- src/OtherAlertableEntity.cpp | 10 ++++--- 12 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 scripts/lua/modules/alert_roles.lua diff --git a/include/AlertableEntity.h b/include/AlertableEntity.h index 7bc1ad17ae..4d928ec8a0 100644 --- a/include/AlertableEntity.h +++ b/include/AlertableEntity.h @@ -54,7 +54,8 @@ class AlertableEntity { virtual void countAlerts(grouped_alerts_counters *counters) {}; virtual void getAlerts(lua_State* vm, ScriptPeriodicity p, - AlertType type_filter, AlertLevel severity_filter, u_int *idx) {}; + AlertType type_filter, AlertLevel severity_filter, AlertRole role_filter, + u_int *idx) {}; bool matchesAllowedNetworks(AddressTree *allowed_nets); diff --git a/include/HostAlertableEntity.h b/include/HostAlertableEntity.h index bf876728d0..50fc08ec2a 100644 --- a/include/HostAlertableEntity.h +++ b/include/HostAlertableEntity.h @@ -49,7 +49,8 @@ class HostAlertableEntity : public AlertableEntity { void countAlerts(grouped_alerts_counters *counters); void getAlerts(lua_State* vm, ScriptPeriodicity p, - AlertType type_filter, AlertLevel severity_filter, u_int *idx); + AlertType type_filter, AlertLevel severity_filter, AlertRole role_filter, + u_int *idx); }; #endif diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index bb41614160..29df5d8250 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -985,7 +985,7 @@ class NetworkInterface : public NetworkInterfaceAlertableEntity { void walkAlertables(AlertEntity alert_entity, const char *entity_value, AddressTree *allowed_nets, alertable_callback *callback, void *user_data); void getEngagedAlerts(lua_State *vm, AlertEntity alert_entity, const char *entity_value, AlertType alert_type, - AlertLevel alert_severity, AddressTree *allowed_nets); + AlertLevel alert_severity, AlertRole role_filter, AddressTree *allowed_nets); /* unlockExternalAlertable must be called after use whenever a non-null reference is returned */ AlertableEntity* lockExternalAlertable(AlertEntity entity, const char *entity_val, bool create_if_missing); diff --git a/include/OtherAlertableEntity.h b/include/OtherAlertableEntity.h index b786d914e6..d9eb8a86b9 100644 --- a/include/OtherAlertableEntity.h +++ b/include/OtherAlertableEntity.h @@ -44,7 +44,8 @@ class OtherAlertableEntity : public AlertableEntity { std::map engaged_alerts[MAX_NUM_PERIODIC_SCRIPTS]; void getPeriodicityAlerts(lua_State* vm, ScriptPeriodicity p, - AlertType type_filter, AlertLevel severity_filter, u_int *idx); + AlertType type_filter, AlertLevel severity_filter, + AlertRole role_filter, u_int *idx); public: OtherAlertableEntity(NetworkInterface *alert_iface, AlertEntity entity); @@ -76,7 +77,8 @@ public: void luaAlert(lua_State* vm, const Alert *alert, ScriptPeriodicity p) const; void countAlerts(grouped_alerts_counters *counters); void getAlerts(lua_State* vm, ScriptPeriodicity p, AlertType type_filter, - AlertLevel severity_filter, u_int *idx); + AlertLevel severity_filter, AlertRole role_filter, + u_int *idx); }; #endif diff --git a/include/ntop_typedefs.h b/include/ntop_typedefs.h index 984165d321..c426f65dcd 100644 --- a/include/ntop_typedefs.h +++ b/include/ntop_typedefs.h @@ -189,6 +189,17 @@ typedef enum { ALERT_LEVEL_GROUP_MAX_LEVEL = 4, } AlertLevelGroup; +/* + Used to filter engaged alerts according to the role + NOTE: Keep in sync with Lua alert_roles.lua + */ +typedef enum { + alert_role_any = 0, + alert_role_is_attacker = 1, + alert_role_is_victim = 2, + alert_role_is_both = 3, +} AlertRole; + /* Keep in sync with alert_entities.lua entity_id */ diff --git a/scripts/lua/modules/alert_roles.lua b/scripts/lua/modules/alert_roles.lua new file mode 100644 index 0000000000..390c035fbe --- /dev/null +++ b/scripts/lua/modules/alert_roles.lua @@ -0,0 +1,30 @@ +-- +-- (C) 2018 - ntop.org +-- +-- This file contains the alert roles constants + +local dirs = ntop.getDirs() + +-- ################################################################################ + + +-- Alerts (Keep role_id in sync with ntop_typedefs.h AlertRole) +local alert_roles = { + alert_role_any = { + role_id = 0, + -- TODO: if necessary, extend this with emoji, labels, etc. + }, + alert_role_is_attacker = { + role_id = 1, + }, + alert_role_is_victim = { + role_id = 2, + }, + alert_role_is_both = { + role_id = 3, + }, +} + +-- ################################################################################ + +return alert_roles diff --git a/scripts/lua/modules/alert_store/alert_store.lua b/scripts/lua/modules/alert_store/alert_store.lua index d82a8f1c53..d7f090fdfa 100644 --- a/scripts/lua/modules/alert_store/alert_store.lua +++ b/scripts/lua/modules/alert_store/alert_store.lua @@ -13,6 +13,7 @@ local format_utils = require "format_utils" local alert_consts = require "alert_consts" local alert_utils = require "alert_utils" local alert_severities = require "alert_severities" +local alert_roles = require "alert_roles" -- ############################################## @@ -291,9 +292,11 @@ function alert_store:select_engaged(filter) local severity_filter = tonumber(self._alert_severity) local entity_id_filter = tonumber(self._alert_entity and self._alert_entity.entity_id) -- Possibly set in subclasses constructor local entity_value_filter = filter or self._entity_value + -- Role is currently supported and populated for hosts engaged alerts. + local role_filter = tonumber(self._role) or alert_roles.alert_role_any.role_id -- tprint(string.format("id=%s sev=%s entity=%s val=%s", alert_id_filter, severity_filter, entity_id_filter, entity_value_filter)) - local alerts = interface.getEngagedAlerts(entity_id_filter, entity_value_filter, alert_id_filter, severity_filter) + local alerts = interface.getEngagedAlerts(entity_id_filter, entity_value_filter, alert_id_filter, severity_filter, role_filter) local total_rows = 0 local sort_2_col = {} diff --git a/scripts/lua/modules/alert_store/host_alert_store.lua b/scripts/lua/modules/alert_store/host_alert_store.lua index 836cc5f672..6b936f8246 100644 --- a/scripts/lua/modules/alert_store/host_alert_store.lua +++ b/scripts/lua/modules/alert_store/host_alert_store.lua @@ -15,6 +15,7 @@ local format_utils = require "format_utils" local alert_consts = require "alert_consts" local alert_utils = require "alert_utils" local alert_entities = require "alert_entities" +local alert_roles = require "alert_roles" local json = require "dkjson" -- ############################################## @@ -105,8 +106,10 @@ function host_alert_store:add_role_filter(role) if not self._role then self._role = role if role == 'attacker' then + self._role = alert_roles.alert_role_is_attacker.role_id self._where[#self._where + 1] = "is_attacker = 1" elseif role == 'victim' then + self._role = alert_roles.alert_role_is_victim.role_id self._where[#self._where + 1] = "is_victim = 1" end return true diff --git a/src/HostAlertableEntity.cpp b/src/HostAlertableEntity.cpp index c5f0b20ba8..2c2787cc54 100644 --- a/src/HostAlertableEntity.cpp +++ b/src/HostAlertableEntity.cpp @@ -162,15 +162,22 @@ void HostAlertableEntity::luaAlert(lua_State* vm, HostAlert *alert) { /* ****************************************** */ void HostAlertableEntity::getAlerts(lua_State* vm, ScriptPeriodicity p /* not used */, - AlertType type_filter, AlertLevel severity_filter, u_int *idx) { + AlertType type_filter, AlertLevel severity_filter, AlertRole role_filter, + u_int *idx) { engaged_alerts_lock.rdlock(__FILE__, __LINE__); for (u_int i = 0; i < NUM_DEFINED_HOST_CALLBACKS; i++) { HostAlert *alert = engaged_alerts[i]; if (alert) { - if ((type_filter == alert_none || type_filter == alert->getAlertType().id) && - (severity_filter == alert_level_none || severity_filter == Utils::mapScoreToSeverity(alert->getScore()))) { + if((type_filter == alert_none + || type_filter == alert->getAlertType().id) + && (severity_filter == alert_level_none + || severity_filter == Utils::mapScoreToSeverity(alert->getScore())) + && (role_filter == alert_role_any + || (role_filter == alert_role_is_attacker && alert->isAttacker()) + || (role_filter == alert_role_is_victim && alert->isVictim()) + || (role_filter == alert_role_is_both && (alert->isAttacker() || alert->isVictim())))) { lua_newtable(vm); luaAlert(vm, alert); diff --git a/src/LuaEngineInterface.cpp b/src/LuaEngineInterface.cpp index 136edfc99c..94c65c88d3 100644 --- a/src/LuaEngineInterface.cpp +++ b/src/LuaEngineInterface.cpp @@ -806,7 +806,7 @@ int ntop_get_alerts(lua_State* vm, AlertableEntity *entity) { if(lua_type(vm, 1) == LUA_TNUMBER) periodicity = (ScriptPeriodicity)lua_tointeger(vm, 1); lua_newtable(vm); - entity->getAlerts(vm, periodicity, alert_none, alert_level_none, &idx); + entity->getAlerts(vm, periodicity, alert_none, alert_level_none, alert_role_any, &idx); return(CONST_LUA_OK); } @@ -898,6 +898,7 @@ static int ntop_interface_get_engaged_alerts(lua_State* vm) { const char *entity_value = NULL; AlertType alert_type = alert_none; AlertLevel alert_severity = alert_level_none; + AlertRole role_filter = alert_role_any; NetworkInterface *iface = getCurrentInterface(vm); AddressTree *allowed_nets = get_allowed_nets(vm); @@ -908,8 +909,9 @@ static int ntop_interface_get_engaged_alerts(lua_State* vm) { if(lua_type(vm, 2) == LUA_TSTRING) entity_value = (char*)lua_tostring(vm, 2); if(lua_type(vm, 3) == LUA_TNUMBER) alert_type = (AlertType)lua_tointeger(vm, 3); if(lua_type(vm, 4) == LUA_TNUMBER) alert_severity = (AlertLevel)lua_tointeger(vm, 4); + if(lua_type(vm, 5) == LUA_TNUMBER) role_filter = (AlertRole)lua_tointeger(vm, 5); - iface->getEngagedAlerts(vm, entity_type, entity_value, alert_type, alert_severity, allowed_nets); + iface->getEngagedAlerts(vm, entity_type, entity_value, alert_type, alert_severity, role_filter, allowed_nets); return(CONST_LUA_OK); } diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 7d723a773d..ff0d8ec42a 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -8392,18 +8392,19 @@ struct get_engaged_alerts_userdata { AlertEntity alert_entity; AlertType alert_type; AlertLevel alert_severity; + AlertRole role_filter; u_int idx; }; static void get_engaged_alerts_callback(AlertEntity alert_entity, AlertableEntity *alertable, void *user_data) { struct get_engaged_alerts_userdata *data = (struct get_engaged_alerts_userdata *)user_data; - alertable->getAlerts(data->vm, no_periodicity, data->alert_type, data->alert_severity, &data->idx); + alertable->getAlerts(data->vm, no_periodicity, data->alert_type, data->alert_severity, data->role_filter, &data->idx); } void NetworkInterface::getEngagedAlerts(lua_State *vm, AlertEntity alert_entity, const char *entity_value, AlertType alert_type, AlertLevel alert_severity, - AddressTree *allowed_nets) { + AlertRole role_filter, AddressTree *allowed_nets) { struct get_engaged_alerts_userdata data; data.vm = vm; @@ -8411,6 +8412,7 @@ void NetworkInterface::getEngagedAlerts(lua_State *vm, AlertEntity alert_entity, data.alert_entity = alert_entity; data.alert_type = alert_type; data.alert_severity = alert_severity; + data.role_filter = role_filter; lua_newtable(vm); diff --git a/src/OtherAlertableEntity.cpp b/src/OtherAlertableEntity.cpp index 0b8e99023e..664a28fea8 100644 --- a/src/OtherAlertableEntity.cpp +++ b/src/OtherAlertableEntity.cpp @@ -160,7 +160,8 @@ void OtherAlertableEntity::countAlerts(grouped_alerts_counters *counters) { /* ****************************************** */ void OtherAlertableEntity::getPeriodicityAlerts(lua_State* vm, ScriptPeriodicity p, - AlertType type_filter, AlertLevel severity_filter, u_int *idx) { + AlertType type_filter, AlertLevel severity_filter, + AlertRole role_filter, u_int *idx) { std::map::const_iterator it; if(!engaged_alerts[p].empty()) { @@ -189,14 +190,15 @@ void OtherAlertableEntity::getPeriodicityAlerts(lua_State* vm, ScriptPeriodicity /* ****************************************** */ void OtherAlertableEntity::getAlerts(lua_State* vm, ScriptPeriodicity periodicity_filter, - AlertType type_filter, AlertLevel severity_filter, u_int *idx) { + AlertType type_filter, AlertLevel severity_filter, AlertRole role_filter, + u_int *idx) { if(periodicity_filter != no_periodicity) { /* Get alerts about a specific periodicity */ - getPeriodicityAlerts(vm, periodicity_filter, type_filter, severity_filter, idx); + getPeriodicityAlerts(vm, periodicity_filter, type_filter, severity_filter, role_filter, idx); } else { int p; for(p = 0; p < MAX_NUM_PERIODIC_SCRIPTS; p++) - getPeriodicityAlerts(vm, (ScriptPeriodicity)p, type_filter, severity_filter, idx); + getPeriodicityAlerts(vm, (ScriptPeriodicity)p, type_filter, severity_filter, role_filter, idx); } }