zeek/policy/targeted-scan.bro

114 lines
2.7 KiB
Text

# $Id:$
#
# Drop external hosts that continually bang away on a particular open port.
#
# Note that we time out identified scanners to avoid excessive memory
# utilitization in the event of a wide scan across address space.
@load notice
@load site
module TargetedScan;
export {
redef enum Notice += { TargetedScan, };
# If true, then only consider traffic from external sources.
global external_only = T &redef;
# Which ports to consider.
const ports = { 1433/tcp, } &redef;
# If set, at least/most this many bytes need to be transferred for
# a connection using the given port. These are useful for example
# for inferring that SSH connections reflect password-guessing
# attempts.
const min_bytes: table[port] of count &redef;
const max_bytes: table[port] of count &redef;
# If set, then this is the threshold for reportin accessing
# for a given service.
const port_threshold: table[port] of count &redef;
# Otherwise, this is the threshold.
const general_threshold = 1000 &redef;
# The data structure we use to track targeted probing.
# It's exported to enable redef'ing the &write_expire value.
global targeted_tries: table[addr, addr, port] of count
&default=0 &write_expire=10 min &redef;
}
function delete_targeted_data(orig: addr, resp: addr, service: port)
{
delete targeted_tries[orig, resp, service];
}
function targeted_check(c: connection)
{
local id = c$id;
local orig = id$orig_h;
local resp = id$resp_h;
local service = ("ftp-data" in c$service) ? 20/tcp : id$resp_p;
if ( service !in ports || (external_only && is_local_addr(orig)) )
return;
local bytes_xferred = c$orig$size + c$resp$size;
if ( service in min_bytes && bytes_xferred < min_bytes[service] )
return;
if ( service in max_bytes && bytes_xferred > max_bytes[service] )
return;
local cnt = ++targeted_tries[orig, resp, service];
if ( service in port_threshold )
{
if ( cnt != port_threshold[service] )
return;
}
else if ( cnt != general_threshold )
return;
local svc = service in port_names ?
port_names[service] : fmt("%s", service);
NOTICE([$note=TargetedScan, $src=orig, $dst=resp, $p=service,
$msg=fmt("targeted attack on service %s, count = %d", svc, cnt)]);
# Since we've reported this host, we can stop tracking it.
delete targeted_tries[orig, resp, service];
}
event connection_finished(c: connection)
{
targeted_check(c);
}
event connection_rejected(c: connection)
{
targeted_check(c);
}
event connection_half_finished(c: connection)
{
targeted_check(c);
}
event connection_reset(c: connection)
{
targeted_check(c);
}
event connection_partial_close(c: connection)
{
targeted_check(c);
}
event connection_state_remove(c: connection)
{
targeted_check(c);
}