mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-30 07:59:35 +00:00
Add Lua host check example (Suspicious Domain Scans) #8956
This commit is contained in:
parent
8d7e968f35
commit
31752105d9
6 changed files with 220 additions and 2 deletions
|
|
@ -0,0 +1,142 @@
|
|||
--
|
||||
-- (C) 2019-24 - ntop.org
|
||||
--
|
||||
|
||||
-- Check notes:
|
||||
-- This check implements a periodic Lua check for triggering host alerts
|
||||
-- Please note this actually runs periodically on an interface and should be used
|
||||
-- to run queries on the database or scan hosts, it is NOT called for each host.
|
||||
-- Only store() should be used, trigger/release (engaged alerts) are not supported
|
||||
|
||||
local checks = require("checks")
|
||||
local alerts_api = require "alerts_api"
|
||||
local alert_consts = require("alert_consts")
|
||||
local host_alert_keys = require "host_alert_keys"
|
||||
local alert_entities = require "alert_entities"
|
||||
|
||||
-- #################################################################
|
||||
|
||||
local script = {
|
||||
edition = "enterprise_m",
|
||||
category = checks.check_categories.security,
|
||||
severity = alert_consts.get_printable_severities().error,
|
||||
alert_id = host_alert_keys.host_alert_suspicious_domain_scan,
|
||||
|
||||
-- This module is disabled by default
|
||||
default_enabled = false,
|
||||
|
||||
-- Default value (reset with "Reset Default" button)
|
||||
default_value = {
|
||||
operator = "gt",
|
||||
threshold = 100,
|
||||
},
|
||||
|
||||
gui = {
|
||||
i18n_title = "flow_checks.suspicious_domain_scan_title",
|
||||
i18n_description = "flow_checks.suspicious_domain_scan_description",
|
||||
i18n_field_unit = checks.field_units.domains,
|
||||
input_builder = "threshold_cross",
|
||||
field_min = 1,
|
||||
field_max = 1000,
|
||||
field_operator = "gt";
|
||||
},
|
||||
|
||||
hooks = {},
|
||||
}
|
||||
|
||||
-- #################################################################
|
||||
|
||||
local function report_host(params, ip, vlan, victim, num_domains)
|
||||
local hostinfo = {
|
||||
host = ip,
|
||||
vlan = vlan
|
||||
}
|
||||
local descr = ""
|
||||
local score = 100
|
||||
|
||||
-- Generate alert
|
||||
|
||||
local alert = alert_consts.alert_types.host_alert_suspicious_domain_scan.new(
|
||||
interface.getId(),
|
||||
victim,
|
||||
num_domains
|
||||
)
|
||||
|
||||
local host_key = hostinfo2hostkey(hostinfo)
|
||||
alert:set_subtype(host_key)
|
||||
alert:set_score(score)
|
||||
alert:set_category(checks.check_categories.security)
|
||||
alert:set_info(params)
|
||||
|
||||
local alert_info = {
|
||||
entity_val = host_key,
|
||||
alert_entity = alert_entities.host
|
||||
}
|
||||
|
||||
alert:store(alert_info)
|
||||
end
|
||||
|
||||
-- #################################################################
|
||||
|
||||
local function domains_check(params)
|
||||
|
||||
-- Settings
|
||||
local threshold = tonumber(params.check_config.threshold) or script.default_value.threshold
|
||||
local interval_size = 60*60 -- 1 hour
|
||||
|
||||
if not ntop.isClickHouseEnabled() then
|
||||
return
|
||||
end
|
||||
|
||||
local now = os.time()
|
||||
local interval_begin = now - interval_size
|
||||
local interval_end = now
|
||||
|
||||
local q = string.format(
|
||||
"SELECT f.ip_src_4, f.ip_src_6, f.ip_dst_4, f.ip_dst_6, count FROM ("
|
||||
.. "SELECT "
|
||||
.. "VLAN_ID vlan_id, "
|
||||
.. "IPv4NumToString(IPV4_SRC_ADDR) ip_src_4, "
|
||||
.. "IPv6NumToString(IPV6_SRC_ADDR) ip_src_6, "
|
||||
.. "IPv4NumToString(IPV4_DST_ADDR) ip_dst_4, "
|
||||
.. "IPv6NumToString(IPV6_DST_ADDR) ip_dst_6, "
|
||||
.. "COUNT(DISTINCT DOMAIN_NAME) AS count "
|
||||
.. "FROM flows "
|
||||
.. "WHERE INTERFACE_ID=%u "
|
||||
.. "AND DOMAIN_NAME!='' "
|
||||
.. "AND (L7_PROTO!=5 AND L7_PROTO_MASTER!=5) AND L7_PROTO_MASTER!=5 "
|
||||
.. "AND (FIRST_SEEN >= %u AND FIRST_SEEN <= %u AND LAST_SEEN <= %u) "
|
||||
.. "GROUP BY VLAN_ID, IPV4_SRC_ADDR, IPV6_SRC_ADDR, IPV4_DST_ADDR, IPV6_DST_ADDR "
|
||||
.. "ORDER BY count DESC "
|
||||
.. ") f WHERE f.count > %u",
|
||||
tonumber(interface.getId()),
|
||||
interval_begin, interval_end, interval_end,
|
||||
threshold
|
||||
)
|
||||
|
||||
local results = interface.execSQLQuery(q)
|
||||
|
||||
for _, row in ipairs(results) do
|
||||
local count = tonumber(row.count) or 0
|
||||
if count > threshold then
|
||||
local vlan_id = tonumber(row.vlan_id) or 0
|
||||
|
||||
local ip = row.ip_src_4
|
||||
if row.ip_src_6 and row.ip_src_6 ~= '::' then ip = row.ip_src_6 end
|
||||
|
||||
local victim_ip = row.ip_dst_4
|
||||
if row.ip_dst_6 and row.ip_dst_6 ~= '::' then victim_ip = row.ip_dst_6 end
|
||||
|
||||
report_host(params, ip, vlan_id, victim_ip, count)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- #################################################################
|
||||
|
||||
script.hooks.hour = domains_check
|
||||
|
||||
-- #################################################################
|
||||
|
||||
return script
|
||||
Loading…
Add table
Add a link
Reference in a new issue