mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 00:28:21 +00:00
Deleting scripts that aren't ready to be included.
- scan.bro and hot.conn.bro will be returning soon. - The rest are going to return as updated protocol analysis scripts and new/updated frameworks later.
This commit is contained in:
parent
827dcea586
commit
19f1e34408
5 changed files with 0 additions and 1054 deletions
|
@ -1,3 +0,0 @@
|
||||||
# If we asked the Time Machine to capture, the filename prefix.
|
|
||||||
# TODO: implement this as a timemachine/notice.bro script?
|
|
||||||
#captured: string &optional;
|
|
|
@ -1,98 +0,0 @@
|
||||||
##! This script makes it possible for the HTTP analysis scripts to analyze
|
|
||||||
##! the apparent normal case of "206 Partial Content" responses.
|
|
||||||
##!
|
|
||||||
##! This script doesn't work yet and isn't loaded by default.
|
|
||||||
|
|
||||||
@load base/frameworks/notice
|
|
||||||
@load ./main
|
|
||||||
@load ./utils
|
|
||||||
|
|
||||||
module HTTP;
|
|
||||||
|
|
||||||
export {
|
|
||||||
redef enum Notice::Type += {
|
|
||||||
Partial_Content_Out_Of_Order,
|
|
||||||
};
|
|
||||||
|
|
||||||
type Range: record {
|
|
||||||
from: count;
|
|
||||||
to: count;
|
|
||||||
} &log;
|
|
||||||
|
|
||||||
redef record Info += {
|
|
||||||
current_range: count &default=0;
|
|
||||||
request_ranges: vector of Range &optional;
|
|
||||||
response_range: Range &optional;
|
|
||||||
};
|
|
||||||
|
|
||||||
## Index is client IP address, server IP address, and URL being requested. The
|
|
||||||
## URL is tracked as part of the index in case multiple partial content segmented
|
|
||||||
## files are being transferred simultaneously between the server and client.
|
|
||||||
global partial_content_files: table[addr, addr, string] of Info &read_expire=5mins &redef;
|
|
||||||
}
|
|
||||||
|
|
||||||
event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=2
|
|
||||||
{
|
|
||||||
local parts: table[count] of string;
|
|
||||||
if ( is_orig && name == "RANGE" )
|
|
||||||
{
|
|
||||||
# Example --> Range: bytes=1-1,2336-4951
|
|
||||||
parts = split(value, /[=]/);
|
|
||||||
if ( 2 in parts )
|
|
||||||
{
|
|
||||||
local ranges = split(parts[2], /,/);
|
|
||||||
for ( i in ranges )
|
|
||||||
{
|
|
||||||
if ( ! c$http?$request_ranges )
|
|
||||||
c$http$request_ranges = vector();
|
|
||||||
parts = split(ranges[i], /-/);
|
|
||||||
local r: Range = [$from=extract_count(parts[1]), $to=extract_count(parts[2])];
|
|
||||||
print r;
|
|
||||||
c$http$request_ranges[|c$http$request_ranges|] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( ! is_orig && name == "CONTENT-RANGE" )
|
|
||||||
{
|
|
||||||
# Example --> Content-Range: bytes 2336-4951/489528
|
|
||||||
parts = split(value, /[0-9]*/);
|
|
||||||
|
|
||||||
c$http$response_range = [$from=extract_count(parts[2]), $to=extract_count(parts[4])];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event http_reply(c: connection, version: string, code: count, reason: string) &priority=5
|
|
||||||
{
|
|
||||||
if ( code != 206 || ! c$http?$request_ranges )
|
|
||||||
return;
|
|
||||||
|
|
||||||
local url = build_url(c$http);
|
|
||||||
if ( [c$id$orig_h, c$id$resp_h, url] !in partial_content_files )
|
|
||||||
{
|
|
||||||
partial_content_files[c$id$orig_h, c$id$resp_h, url] = copy(c$http);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event http_entity_data(c: connection, is_orig: bool, length: count, data: string)
|
|
||||||
{
|
|
||||||
if ( is_orig || c$http$status_code != 206 || ! c$http?$request_ranges )
|
|
||||||
return;
|
|
||||||
|
|
||||||
local url = build_url(c$http);
|
|
||||||
local http = partial_content_files[c$id$orig_h, c$id$resp_h, url];
|
|
||||||
local range = http$request_ranges[http$current_range];
|
|
||||||
|
|
||||||
print http$current_range;
|
|
||||||
if ( http$current_range == 0 &&
|
|
||||||
c$http$response_range$from == 0 )
|
|
||||||
{
|
|
||||||
print "correct file beginning!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event http_end_entity(c: connection, is_orig: bool)
|
|
||||||
{
|
|
||||||
print "end entity";
|
|
||||||
++c$http$current_range;
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
|
|
||||||
#
|
|
||||||
# Log RPC request and reply messages. Does not in itself start/activate
|
|
||||||
# an analyzer. You need to load portmap and/or NFS for that
|
|
||||||
#
|
|
||||||
# TODO: maybe automatically load portmap, add a generic RPC analyzer and
|
|
||||||
# use expect connection, so that we can see RPC request/replies for RPC
|
|
||||||
# programs for which we don't have an analyzer.
|
|
||||||
#
|
|
||||||
|
|
||||||
@load base/utils/conn-ids
|
|
||||||
|
|
||||||
module RPC;
|
|
||||||
|
|
||||||
export {
|
|
||||||
global log_file = open_log_file("rpc") &redef;
|
|
||||||
# whether to match request to replies on the policy layer.
|
|
||||||
# (will report on rexmit and missing requests or replies)
|
|
||||||
global track_requests_replies = T &redef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
type rpc_call_state: enum {
|
|
||||||
NONE,
|
|
||||||
HAVE_CALL,
|
|
||||||
HAVE_REPLY
|
|
||||||
};
|
|
||||||
|
|
||||||
type rpc_call_info: record {
|
|
||||||
state: rpc_call_state;
|
|
||||||
calltime: time;
|
|
||||||
cid: conn_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
function new_call(cid: conn_id): rpc_call_info
|
|
||||||
{
|
|
||||||
local ci: rpc_call_info;
|
|
||||||
|
|
||||||
ci$state = NONE;
|
|
||||||
ci$calltime = network_time();
|
|
||||||
ci$cid = cid;
|
|
||||||
return ci;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rpc_expire_xid(t: table[count] of rpc_call_info, xid: count): interval
|
|
||||||
{
|
|
||||||
local ci = t[xid];
|
|
||||||
if (ci$state != HAVE_REPLY)
|
|
||||||
print log_file, fmt("%.6f %s %s note XID %d never recevied a reply",
|
|
||||||
ci$calltime, id_string(ci$cid),
|
|
||||||
get_port_transport_proto(ci$cid$orig_p), xid);
|
|
||||||
return 0 sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
function new_xid_table(): table[count] of rpc_call_info
|
|
||||||
{
|
|
||||||
local inner: table[count] of rpc_call_info &write_expire=rpc_timeout &expire_func=rpc_expire_xid;
|
|
||||||
return inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Match requests to replies.
|
|
||||||
# The analyzer does this indepently and might differ in timeouts and
|
|
||||||
# handling of xid reuse.
|
|
||||||
# FIXME: add timeouts. Note, we do clean up on connection_state_remove
|
|
||||||
global rpc_calls: table[conn_id] of table[count] of rpc_call_info;
|
|
||||||
# &write_expire = rpc_timeout &expire_func=expire_rpc_call;
|
|
||||||
|
|
||||||
|
|
||||||
event rpc_dialogue(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count)
|
|
||||||
{
|
|
||||||
# TODO: We currently do nothing here.
|
|
||||||
# using the rpc_call and rpc_reply events, is all we need.
|
|
||||||
}
|
|
||||||
|
|
||||||
event rpc_call(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count)
|
|
||||||
{
|
|
||||||
if (track_requests_replies)
|
|
||||||
{
|
|
||||||
if (c$id !in rpc_calls)
|
|
||||||
rpc_calls[c$id] = new_xid_table();
|
|
||||||
if (xid !in rpc_calls[c$id])
|
|
||||||
rpc_calls[c$id][xid] = new_call(c$id);
|
|
||||||
local curstate = rpc_calls[c$id][xid]$state;
|
|
||||||
|
|
||||||
if (curstate == HAVE_CALL)
|
|
||||||
print log_file, fmt("%.6f %s %s note XID %d call retransmitted",
|
|
||||||
network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid);
|
|
||||||
else if (curstate == HAVE_REPLY)
|
|
||||||
print log_file, fmt("%.6f %s %s note XID %d call received after reply",
|
|
||||||
network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid);
|
|
||||||
rpc_calls[c$id][xid]$state = HAVE_CALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
print log_file, fmt("%.6f %s %s rpc_call %d %d %d %d %d",
|
|
||||||
network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid, prog, ver, proc, call_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
event rpc_reply(c: connection, xid: count, status: rpc_status, reply_len: count)
|
|
||||||
{
|
|
||||||
if (track_requests_replies)
|
|
||||||
{
|
|
||||||
if (c$id !in rpc_calls)
|
|
||||||
rpc_calls[c$id] = new_xid_table();
|
|
||||||
if (xid !in rpc_calls[c$id])
|
|
||||||
{
|
|
||||||
rpc_calls[c$id][xid] = new_call(c$id);
|
|
||||||
# XXX: what to do about calltime in rpc_call_info??
|
|
||||||
}
|
|
||||||
if (rpc_calls[c$id][xid]$state == NONE)
|
|
||||||
print log_file, fmt("%.6f %s %s note XID %d reply but call is missing",
|
|
||||||
network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid);
|
|
||||||
else if (rpc_calls[c$id][xid]$state == HAVE_REPLY)
|
|
||||||
print log_file, fmt("%.6f %s %s note XID %d reply retransmitted",
|
|
||||||
network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid);
|
|
||||||
rpc_calls[c$id][xid]$state = HAVE_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
print log_file, fmt("%.6f %s %s rpc_reply %d %s %d",
|
|
||||||
network_time(), reverse_id_string(c$id), get_port_transport_proto(c$id$orig_p),
|
|
||||||
xid, status, reply_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function finish_calls(cid: conn_id)
|
|
||||||
{
|
|
||||||
for (xid in rpc_calls[cid])
|
|
||||||
rpc_expire_xid(rpc_calls[cid], xid);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_state_remove(c: connection)
|
|
||||||
{
|
|
||||||
if (c$id !in rpc_calls)
|
|
||||||
return;
|
|
||||||
finish_calls(c$id);
|
|
||||||
delete rpc_calls[c$id];
|
|
||||||
}
|
|
||||||
|
|
||||||
event bro_done()
|
|
||||||
{
|
|
||||||
for (cid in rpc_calls)
|
|
||||||
finish_calls(cid);
|
|
||||||
}
|
|
|
@ -1,200 +0,0 @@
|
||||||
@load hot
|
|
||||||
|
|
||||||
redef enum Notice += {
|
|
||||||
Sensitive_Connection, # connection marked "hot"
|
|
||||||
};
|
|
||||||
|
|
||||||
# Whether to translate the local address in Sensitive_Connection notices
|
|
||||||
# to a hostname. Meant as a demonstration of the "when" construct.
|
|
||||||
const xlate_hot_local_addr = F &redef;
|
|
||||||
|
|
||||||
# The sets are indexed by the complete hot messages.
|
|
||||||
global hot_conns_reported: table[conn_id] of set[string];
|
|
||||||
|
|
||||||
const conn_closed = { TCP_CLOSED, TCP_RESET };
|
|
||||||
|
|
||||||
const state_graphic = {
|
|
||||||
["OTH"] = "?>?", ["REJ"] = "[",
|
|
||||||
["RSTO"] = ">]", ["RSTOS0"] = "}]", ["RSTR"] = ">[", ["RSTRH"] = "<[",
|
|
||||||
["S0"] = "}", ["S1"] = ">", ["S2"] = "}2", ["S3"] = "}3",
|
|
||||||
["SF"] = ">", ["SH"] = ">h", ["SHR"] = "<h",
|
|
||||||
};
|
|
||||||
|
|
||||||
function full_id_string(c: connection): string
|
|
||||||
{
|
|
||||||
local id = c$id;
|
|
||||||
local trans = get_port_transport_proto(id$orig_p);
|
|
||||||
local state = conn_state(c, trans);
|
|
||||||
local state_gr = state_graphic[state];
|
|
||||||
local service = service_name(c);
|
|
||||||
|
|
||||||
if ( state == "S0" || state == "S1" || state == "REJ" )
|
|
||||||
return fmt("%s %s %s/%s %s", id$orig_h, state_gr,
|
|
||||||
id$resp_h, service, c$addl);
|
|
||||||
|
|
||||||
else
|
|
||||||
return fmt("%s %sb %s %s/%s %sb %.1fs %s",
|
|
||||||
id$orig_h, conn_size(c$orig, trans),
|
|
||||||
state_gr, id$resp_h, service,
|
|
||||||
conn_size(c$resp, trans), c$duration, c$addl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Low-level routine that generates the actual Sensitive_Connection
|
|
||||||
# notice associated with a "hot" connection.
|
|
||||||
function do_hot_notice(c: connection, dir: string, host: string)
|
|
||||||
{
|
|
||||||
NOTICE([$note=Sensitive_Connection, $conn=c,
|
|
||||||
$msg=fmt("hot: %s %s local host: %s",
|
|
||||||
full_id_string(c), dir, host)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate a Sensitive_Connection notice with the local hostname
|
|
||||||
# translated. Mostly intended as a demonstration of using "when".
|
|
||||||
function gen_hot_notice_with_hostnames(c: connection)
|
|
||||||
{
|
|
||||||
local id = c$id;
|
|
||||||
local inbound = is_local_addr(id$resp_h);
|
|
||||||
local dir = inbound ? "to" : "from";
|
|
||||||
local local_addr = inbound ? id$orig_h : id$resp_h;
|
|
||||||
|
|
||||||
add_notice_tag(c);
|
|
||||||
|
|
||||||
when ( local hostname = lookup_addr(local_addr) )
|
|
||||||
do_hot_notice(c, dir, hostname);
|
|
||||||
timeout 5 sec
|
|
||||||
{ do_hot_notice(c, dir, fmt("%s", local_addr)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_hot_conn(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$id !in hot_conns_reported )
|
|
||||||
hot_conns_reported[c$id] = set() &mergeable;
|
|
||||||
|
|
||||||
local msg = full_id_string(c);
|
|
||||||
|
|
||||||
if ( msg !in hot_conns_reported[c$id] )
|
|
||||||
{
|
|
||||||
if ( xlate_hot_local_addr )
|
|
||||||
gen_hot_notice_with_hostnames(c);
|
|
||||||
else
|
|
||||||
NOTICE([$note=Sensitive_Connection, $conn=c,
|
|
||||||
$msg=fmt("hot: %s", full_id_string(c))]);
|
|
||||||
|
|
||||||
add hot_conns_reported[c$id][msg];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
event connection_established(c: connection)
|
|
||||||
{
|
|
||||||
Hot::check_hot(c, Hot::CONN_ESTABLISHED);
|
|
||||||
|
|
||||||
if ( c$hot > 0 )
|
|
||||||
log_hot_conn(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_state_remove(c: connection) &priority = -10
|
|
||||||
{
|
|
||||||
local os = c$orig$state;
|
|
||||||
local rs = c$resp$state;
|
|
||||||
|
|
||||||
if ( os == TCP_ESTABLISHED && rs == TCP_ESTABLISHED )
|
|
||||||
# It was still active, no summary generated.
|
|
||||||
connection_gone(c, "remove");
|
|
||||||
|
|
||||||
else if ( (os == TCP_CLOSED || rs == TCP_CLOSED) &&
|
|
||||||
(os == TCP_ESTABLISHED || rs == TCP_ESTABLISHED) )
|
|
||||||
# One side has closed, the other hasn't - it's in state S2
|
|
||||||
# or S3, hasn't been reported yet.
|
|
||||||
connection_gone(c, "remove");
|
|
||||||
|
|
||||||
delete hot_conns_reported[c$id];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
event partial_connection(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE )
|
|
||||||
# This appears to be a stealth scan. Don't do hot-checking
|
|
||||||
# as there wasn't an established connection.
|
|
||||||
;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Hot::check_hot(c, Hot::CONN_ESTABLISHED);
|
|
||||||
Hot::check_hot(c, Hot::APPL_ESTABLISHED); # assume it's been established
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( c$hot > 0 )
|
|
||||||
log_hot_conn(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_attempt(c: connection)
|
|
||||||
{
|
|
||||||
Hot::check_spoof(c);
|
|
||||||
Hot::check_hot(c, Hot::CONN_ATTEMPTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_finished(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$size == 0 || c$resp$size == 0 )
|
|
||||||
# Hard to get excited about this - not worth logging again.
|
|
||||||
c$hot = 0;
|
|
||||||
else
|
|
||||||
Hot::check_hot(c, Hot::CONN_FINISHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_partial_close(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$size == 0 || c$resp$size == 0 )
|
|
||||||
# Hard to get excited about this - not worth logging again.
|
|
||||||
c$hot = 0;
|
|
||||||
else
|
|
||||||
Hot::check_hot(c, Hot::CONN_FINISHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_half_finished(c: connection)
|
|
||||||
{
|
|
||||||
Hot::check_hot(c, Hot::CONN_ATTEMPTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_rejected(c: connection)
|
|
||||||
{
|
|
||||||
Hot::check_hot(c, Hot::CONN_REJECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_reset(c: connection)
|
|
||||||
{
|
|
||||||
Hot::check_hot(c, Hot::CONN_FINISHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_pending(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$state in conn_closed &&
|
|
||||||
(c$resp$state == TCP_INACTIVE || c$resp$state == TCP_PARTIAL) )
|
|
||||||
# This is a stray FIN or RST - don't bother reporting.
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( c$orig$state == TCP_RESET || c$resp$state == TCP_RESET )
|
|
||||||
# We already reported this connection when the RST
|
|
||||||
# occurred.
|
|
||||||
return;
|
|
||||||
|
|
||||||
Hot::check_hot(c, Hot::CONN_FINISHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
function connection_gone(c: connection, gone_type: string)
|
|
||||||
{
|
|
||||||
if ( c$orig$size == 0 || c$resp$size == 0 )
|
|
||||||
{
|
|
||||||
if ( c$orig$state == TCP_RESET && c$resp$state == TCP_INACTIVE)
|
|
||||||
# A bare RST, no other context. Ignore it.
|
|
||||||
return;
|
|
||||||
|
|
||||||
# Hard to get excited about this - not worth logging again,
|
|
||||||
# per connection_finished().
|
|
||||||
c$hot = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Hot::check_hot(c, Hot::CONN_TIMEOUT);
|
|
||||||
}
|
|
|
@ -1,604 +0,0 @@
|
||||||
@load base/frameworks/notice/main
|
|
||||||
@load port-name
|
|
||||||
|
|
||||||
module Scan;
|
|
||||||
|
|
||||||
export {
|
|
||||||
redef enum Notice::Type += {
|
|
||||||
## The source has scanned a number of ports.
|
|
||||||
PortScan,
|
|
||||||
## The source has scanned a number of addresses.
|
|
||||||
AddressScan,
|
|
||||||
## Apparent flooding backscatter seen from source.
|
|
||||||
BackscatterSeen,
|
|
||||||
|
|
||||||
## Summary of scanning activity.
|
|
||||||
ScanSummary,
|
|
||||||
## Summary of distinct ports per scanner.
|
|
||||||
PortScanSummary,
|
|
||||||
## Summary of distinct low ports per scanner.
|
|
||||||
LowPortScanSummary,
|
|
||||||
|
|
||||||
## Source touched a landmine destination.
|
|
||||||
Landmine,
|
|
||||||
## Source reached :bro:id:`Scan::shut_down_threshold`
|
|
||||||
ShutdownThreshold,
|
|
||||||
## Source touched privileged ports.
|
|
||||||
LowPortTrolling,
|
|
||||||
};
|
|
||||||
|
|
||||||
# Whether to consider UDP "connections" for scan detection.
|
|
||||||
# Can lead to false positives due to UDP fanout from some P2P apps.
|
|
||||||
const suppress_UDP_scan_checks = F &redef;
|
|
||||||
|
|
||||||
const activate_priv_port_check = T &redef;
|
|
||||||
const activate_landmine_check = F &redef;
|
|
||||||
const landmine_thresh_trigger = 5 &redef;
|
|
||||||
|
|
||||||
const landmine_address: set[addr] &redef;
|
|
||||||
|
|
||||||
const scan_summary_trigger = 25 &redef;
|
|
||||||
const port_summary_trigger = 20 &redef;
|
|
||||||
const lowport_summary_trigger = 10 &redef;
|
|
||||||
|
|
||||||
# Raise ShutdownThresh after this many failed attempts
|
|
||||||
const shut_down_threshold = 100 &redef;
|
|
||||||
|
|
||||||
# Which services should be analyzed when detecting scanning
|
|
||||||
# (not consulted if analyze_all_services is set).
|
|
||||||
const analyze_services: set[port] &redef;
|
|
||||||
const analyze_all_services = T &redef;
|
|
||||||
|
|
||||||
# Track address scaners only if at least these many hosts contacted.
|
|
||||||
const addr_scan_trigger = 0 &redef;
|
|
||||||
|
|
||||||
# Ignore address scanners for further scan detection after
|
|
||||||
# scanning this many hosts.
|
|
||||||
# 0 disables.
|
|
||||||
const ignore_scanners_threshold = 0 &redef;
|
|
||||||
|
|
||||||
# Report a scan of peers at each of these points.
|
|
||||||
const report_peer_scan: vector of count = {
|
|
||||||
20, 100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
const report_outbound_peer_scan: vector of count = {
|
|
||||||
100, 1000, 10000,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
# Report a scan of ports at each of these points.
|
|
||||||
const report_port_scan: vector of count = {
|
|
||||||
50, 250, 1000, 5000, 10000, 25000, 65000,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
# Once a source has scanned this many different ports (to however many
|
|
||||||
# different remote hosts), start tracking its per-destination access.
|
|
||||||
const possible_port_scan_thresh = 20 &redef;
|
|
||||||
|
|
||||||
# Threshold for scanning privileged ports.
|
|
||||||
const priv_scan_trigger = 5 &redef;
|
|
||||||
const troll_skip_service = {
|
|
||||||
smtp, ftp, ssh, 20/tcp, http,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
const report_accounts_tried: vector of count = {
|
|
||||||
20, 100, 1000, 10000, 100000, 1000000,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
const report_remote_accounts_tried: vector of count = {
|
|
||||||
100, 500,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
# Report a successful password guessing if the source attempted
|
|
||||||
# at least this many.
|
|
||||||
const password_guessing_success_threshhold = 20 &redef;
|
|
||||||
|
|
||||||
const skip_accounts_tried: set[addr] &redef;
|
|
||||||
|
|
||||||
const addl_web = {
|
|
||||||
81/tcp, 443/tcp, 8000/tcp, 8001/tcp, 8080/tcp, }
|
|
||||||
&redef;
|
|
||||||
|
|
||||||
const skip_services = { ident, } &redef;
|
|
||||||
const skip_outbound_services = { Hot::allow_services, ftp, addl_web, }
|
|
||||||
&redef;
|
|
||||||
|
|
||||||
const skip_scan_sources = {
|
|
||||||
255.255.255.255, # who knows why we see these, but we do
|
|
||||||
|
|
||||||
# AltaVista. Here just as an example of what sort of things
|
|
||||||
# you might list.
|
|
||||||
test-scooter.av.pa-x.dec.com,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
const skip_scan_nets: set[subnet] = {} &redef;
|
|
||||||
|
|
||||||
# List of well known local server/ports to exclude for scanning
|
|
||||||
# purposes.
|
|
||||||
const skip_dest_server_ports: set[addr, port] = {} &redef;
|
|
||||||
|
|
||||||
# Reverse (SYN-ack) scans seen from these ports are considered
|
|
||||||
# to reflect possible SYN-flooding backscatter, and not true
|
|
||||||
# (stealth) scans.
|
|
||||||
const backscatter_ports = {
|
|
||||||
http, 53/tcp, 53/udp, bgp, 6666/tcp, 6667/tcp,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
const report_backscatter: vector of count = {
|
|
||||||
20,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
global check_scan:
|
|
||||||
function(c: connection, established: bool, reverse: bool): bool;
|
|
||||||
|
|
||||||
# The following tables are defined here so that we can redef
|
|
||||||
# the expire timeouts.
|
|
||||||
# FIXME: should we allow redef of attributes on IDs which
|
|
||||||
# are not exported?
|
|
||||||
|
|
||||||
# How many different hosts connected to with a possible
|
|
||||||
# backscatter signature.
|
|
||||||
global distinct_backscatter_peers: table[addr] of table[addr] of count
|
|
||||||
&read_expire = 15 min;
|
|
||||||
|
|
||||||
# Expire functions that trigger summaries.
|
|
||||||
global scan_summary:
|
|
||||||
function(t: table[addr] of set[addr], orig: addr): interval;
|
|
||||||
global port_summary:
|
|
||||||
function(t: table[addr] of set[port], orig: addr): interval;
|
|
||||||
global lowport_summary:
|
|
||||||
function(t: table[addr] of set[port], orig: addr): interval;
|
|
||||||
|
|
||||||
# Indexed by scanner address, yields # distinct peers scanned.
|
|
||||||
# pre_distinct_peers tracks until addr_scan_trigger hosts first.
|
|
||||||
global pre_distinct_peers: table[addr] of set[addr]
|
|
||||||
&read_expire = 15 mins &redef;
|
|
||||||
|
|
||||||
global distinct_peers: table[addr] of set[addr]
|
|
||||||
&read_expire = 15 mins &expire_func=scan_summary &redef;
|
|
||||||
global distinct_ports: table[addr] of set[port]
|
|
||||||
&read_expire = 15 mins &expire_func=port_summary &redef;
|
|
||||||
global distinct_low_ports: table[addr] of set[port]
|
|
||||||
&read_expire = 15 mins &expire_func=lowport_summary &redef;
|
|
||||||
|
|
||||||
# Indexed by scanner address, yields a table with scanned hosts
|
|
||||||
# (and ports).
|
|
||||||
global scan_triples: table[addr] of table[addr] of set[port];
|
|
||||||
|
|
||||||
global remove_possible_source:
|
|
||||||
function(s: set[addr], idx: addr): interval;
|
|
||||||
global possible_scan_sources: set[addr]
|
|
||||||
&expire_func=remove_possible_source &read_expire = 15 mins;
|
|
||||||
|
|
||||||
# Indexed by source address, yields user name & password tried.
|
|
||||||
global accounts_tried: table[addr] of set[string, string]
|
|
||||||
&read_expire = 1 days;
|
|
||||||
|
|
||||||
global ignored_scanners: set[addr] &create_expire = 1 day &redef;
|
|
||||||
|
|
||||||
# These tables track whether a threshold has been reached.
|
|
||||||
# More precisely, the counter is the next index of threshold vector.
|
|
||||||
global shut_down_threshold_reached: table[addr] of bool &default=F;
|
|
||||||
global rb_idx: table[addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
global rps_idx: table[addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
global rops_idx: table[addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
global rpts_idx: table[addr,addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
global rat_idx: table[addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
global rrat_idx: table[addr] of count
|
|
||||||
&default=0 &read_expire = 1 days &redef;
|
|
||||||
}
|
|
||||||
|
|
||||||
global thresh_check: function(v: vector of count, idx: table[addr] of count,
|
|
||||||
orig: addr, n: count): bool;
|
|
||||||
global thresh_check_2: function(v: vector of count,
|
|
||||||
idx: table[addr,addr] of count, orig: addr,
|
|
||||||
resp: addr, n: count): bool;
|
|
||||||
|
|
||||||
function scan_summary(t: table[addr] of set[addr], orig: addr): interval
|
|
||||||
{
|
|
||||||
local num_distinct_peers = orig in t ? |t[orig]| : 0;
|
|
||||||
|
|
||||||
if ( num_distinct_peers >= scan_summary_trigger )
|
|
||||||
NOTICE([$note=ScanSummary, $src=orig, $n=num_distinct_peers,
|
|
||||||
$msg=fmt("%s scanned a total of %d hosts",
|
|
||||||
orig, num_distinct_peers)]);
|
|
||||||
|
|
||||||
return 0 secs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function port_summary(t: table[addr] of set[port], orig: addr): interval
|
|
||||||
{
|
|
||||||
local num_distinct_ports = orig in t ? |t[orig]| : 0;
|
|
||||||
|
|
||||||
if ( num_distinct_ports >= port_summary_trigger )
|
|
||||||
NOTICE([$note=PortScanSummary, $src=orig, $n=num_distinct_ports,
|
|
||||||
$msg=fmt("%s scanned a total of %d ports",
|
|
||||||
orig, num_distinct_ports)]);
|
|
||||||
|
|
||||||
return 0 secs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lowport_summary(t: table[addr] of set[port], orig: addr): interval
|
|
||||||
{
|
|
||||||
local num_distinct_lowports = orig in t ? |t[orig]| : 0;
|
|
||||||
|
|
||||||
if ( num_distinct_lowports >= lowport_summary_trigger )
|
|
||||||
NOTICE([$note=LowPortScanSummary, $src=orig,
|
|
||||||
$n=num_distinct_lowports,
|
|
||||||
$msg=fmt("%s scanned a total of %d low ports",
|
|
||||||
orig, num_distinct_lowports)]);
|
|
||||||
|
|
||||||
return 0 secs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear_addr(a: addr)
|
|
||||||
{
|
|
||||||
delete distinct_peers[a];
|
|
||||||
delete distinct_ports[a];
|
|
||||||
delete distinct_low_ports[a];
|
|
||||||
delete scan_triples[a];
|
|
||||||
delete possible_scan_sources[a];
|
|
||||||
delete distinct_backscatter_peers[a];
|
|
||||||
delete pre_distinct_peers[a];
|
|
||||||
delete rb_idx[a];
|
|
||||||
delete rps_idx[a];
|
|
||||||
delete rops_idx[a];
|
|
||||||
delete rat_idx[a];
|
|
||||||
delete rrat_idx[a];
|
|
||||||
delete shut_down_threshold_reached[a];
|
|
||||||
delete ignored_scanners[a];
|
|
||||||
}
|
|
||||||
|
|
||||||
function ignore_addr(a: addr)
|
|
||||||
{
|
|
||||||
clear_addr(a);
|
|
||||||
add ignored_scanners[a];
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_scan(c: connection, established: bool, reverse: bool): bool
|
|
||||||
{
|
|
||||||
local id = c$id;
|
|
||||||
|
|
||||||
local service = "ftp-data" in c$service ? 20/tcp
|
|
||||||
: (reverse ? id$orig_p : id$resp_p);
|
|
||||||
local rev_service = reverse ? id$resp_p : id$orig_p;
|
|
||||||
local orig = reverse ? id$resp_h : id$orig_h;
|
|
||||||
local resp = reverse ? id$orig_h : id$resp_h;
|
|
||||||
local outbound = is_local_addr(orig);
|
|
||||||
|
|
||||||
# The following works better than using get_conn_transport_proto()
|
|
||||||
# because c might not correspond to an active connection (which
|
|
||||||
# causes the function to fail).
|
|
||||||
if ( suppress_UDP_scan_checks &&
|
|
||||||
service >= 0/udp && service <= 65535/udp )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( service in skip_services && ! outbound )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( outbound && service in skip_outbound_services )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( orig in skip_scan_sources )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( orig in skip_scan_nets )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
# Don't include well known server/ports for scanning purposes.
|
|
||||||
if ( ! outbound && [resp, service] in skip_dest_server_ports )
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( orig in ignored_scanners)
|
|
||||||
return F;
|
|
||||||
|
|
||||||
if ( (! established || service !in Hot::allow_services) &&
|
|
||||||
# not established, service not expressly allowed
|
|
||||||
|
|
||||||
# not known peer set
|
|
||||||
(orig !in distinct_peers || resp !in distinct_peers[orig]) &&
|
|
||||||
|
|
||||||
# want to consider service for scan detection
|
|
||||||
(analyze_all_services || service in analyze_services) )
|
|
||||||
{
|
|
||||||
if ( reverse && rev_service in backscatter_ports &&
|
|
||||||
# reverse, non-priv backscatter port
|
|
||||||
service >= 1024/tcp )
|
|
||||||
{
|
|
||||||
if ( orig !in distinct_backscatter_peers )
|
|
||||||
{
|
|
||||||
local empty_bs_table:
|
|
||||||
table[addr] of count &default=0;
|
|
||||||
distinct_backscatter_peers[orig] =
|
|
||||||
empty_bs_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ++distinct_backscatter_peers[orig][resp] <= 2 &&
|
|
||||||
# The test is <= 2 because we get two check_scan()
|
|
||||||
# calls, once on connection attempt and once on
|
|
||||||
# tear-down.
|
|
||||||
|
|
||||||
distinct_backscatter_peers[orig][resp] == 1 &&
|
|
||||||
|
|
||||||
# Looks like backscatter, and it's not scanning
|
|
||||||
# a privileged port.
|
|
||||||
|
|
||||||
thresh_check(report_backscatter, rb_idx, orig,
|
|
||||||
|distinct_backscatter_peers[orig]|)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
local rev_svc = rev_service in port_names ?
|
|
||||||
port_names[rev_service] :
|
|
||||||
fmt("%s", rev_service);
|
|
||||||
|
|
||||||
NOTICE([$note=BackscatterSeen, $src=orig,
|
|
||||||
$p=rev_service,
|
|
||||||
$msg=fmt("backscatter seen from %s (%d hosts; %s)",
|
|
||||||
orig, |distinct_backscatter_peers[orig]|, rev_svc)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ignore_scanners_threshold > 0 &&
|
|
||||||
|distinct_backscatter_peers[orig]| >
|
|
||||||
ignore_scanners_threshold )
|
|
||||||
ignore_addr(orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{ # done with backscatter check
|
|
||||||
local ignore = F;
|
|
||||||
|
|
||||||
local svc = service in port_names ?
|
|
||||||
port_names[service] : fmt("%s", service);
|
|
||||||
|
|
||||||
if ( orig !in distinct_peers && addr_scan_trigger > 0 )
|
|
||||||
{
|
|
||||||
if ( orig !in pre_distinct_peers )
|
|
||||||
pre_distinct_peers[orig] = set();
|
|
||||||
|
|
||||||
add pre_distinct_peers[orig][resp];
|
|
||||||
if ( |pre_distinct_peers[orig]| < addr_scan_trigger )
|
|
||||||
ignore = T;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! ignore )
|
|
||||||
{ # XXXXX
|
|
||||||
|
|
||||||
if ( orig !in distinct_peers )
|
|
||||||
distinct_peers[orig] = set() &mergeable;
|
|
||||||
|
|
||||||
if ( resp !in distinct_peers[orig] )
|
|
||||||
add distinct_peers[orig][resp];
|
|
||||||
|
|
||||||
local n = |distinct_peers[orig]|;
|
|
||||||
|
|
||||||
if ( activate_landmine_check &&
|
|
||||||
n >= landmine_thresh_trigger &&
|
|
||||||
mask_addr(resp, 24) in landmine_address )
|
|
||||||
{
|
|
||||||
local msg2 = fmt("landmine address trigger %s%s ", orig, svc);
|
|
||||||
NOTICE([$note=Landmine, $src=orig,
|
|
||||||
$p=service, $msg=msg2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check for threshold if not outbound.
|
|
||||||
if ( ! shut_down_threshold_reached[orig] &&
|
|
||||||
n >= shut_down_threshold &&
|
|
||||||
! outbound && orig !in neighbor_nets )
|
|
||||||
{
|
|
||||||
shut_down_threshold_reached[orig] = T;
|
|
||||||
local msg = fmt("shutdown threshold reached for %s", orig);
|
|
||||||
NOTICE([$note=ShutdownThreshold, $src=orig,
|
|
||||||
$p=service, $msg=msg]);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
local address_scan = F;
|
|
||||||
if ( outbound &&
|
|
||||||
# inside host scanning out?
|
|
||||||
thresh_check(report_outbound_peer_scan, rops_idx, orig, n) )
|
|
||||||
address_scan = T;
|
|
||||||
|
|
||||||
if ( ! outbound &&
|
|
||||||
thresh_check(report_peer_scan, rps_idx, orig, n) )
|
|
||||||
address_scan = T;
|
|
||||||
|
|
||||||
if ( address_scan )
|
|
||||||
NOTICE([$note=AddressScan,
|
|
||||||
$src=orig, $p=service,
|
|
||||||
$n=n,
|
|
||||||
$msg=fmt("%s has scanned %d hosts (%s)",
|
|
||||||
orig, n, svc)]);
|
|
||||||
|
|
||||||
if ( address_scan &&
|
|
||||||
ignore_scanners_threshold > 0 &&
|
|
||||||
n > ignore_scanners_threshold )
|
|
||||||
ignore_addr(orig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} # XXXX
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( established )
|
|
||||||
# Don't consider established connections for port scanning,
|
|
||||||
# it's too easy to be mislead by FTP-like applications that
|
|
||||||
# legitimately gobble their way through the port space.
|
|
||||||
return F;
|
|
||||||
|
|
||||||
# Coarse search for port-scanning candidates: those that have made
|
|
||||||
# connections (attempts) to possible_port_scan_thresh or more
|
|
||||||
# distinct ports.
|
|
||||||
if ( orig !in distinct_ports || service !in distinct_ports[orig] )
|
|
||||||
{
|
|
||||||
if ( orig !in distinct_ports )
|
|
||||||
distinct_ports[orig] = set() &mergeable;
|
|
||||||
|
|
||||||
if ( service !in distinct_ports[orig] )
|
|
||||||
add distinct_ports[orig][service];
|
|
||||||
|
|
||||||
if ( |distinct_ports[orig]| >= possible_port_scan_thresh &&
|
|
||||||
orig !in scan_triples )
|
|
||||||
{
|
|
||||||
scan_triples[orig] = table() &mergeable;
|
|
||||||
add possible_scan_sources[orig];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# For sources that have been identified as possible scan sources,
|
|
||||||
# keep track of per-host scanning.
|
|
||||||
if ( orig in possible_scan_sources )
|
|
||||||
{
|
|
||||||
if ( orig !in scan_triples )
|
|
||||||
scan_triples[orig] = table() &mergeable;
|
|
||||||
|
|
||||||
if ( resp !in scan_triples[orig] )
|
|
||||||
scan_triples[orig][resp] = set() &mergeable;
|
|
||||||
|
|
||||||
if ( service !in scan_triples[orig][resp] )
|
|
||||||
{
|
|
||||||
add scan_triples[orig][resp][service];
|
|
||||||
|
|
||||||
if ( thresh_check_2(report_port_scan, rpts_idx,
|
|
||||||
orig, resp,
|
|
||||||
|scan_triples[orig][resp]|) )
|
|
||||||
{
|
|
||||||
local m = |scan_triples[orig][resp]|;
|
|
||||||
NOTICE([$note=PortScan, $n=m, $src=orig,
|
|
||||||
$p=service,
|
|
||||||
$msg=fmt("%s has scanned %d ports of %s", orig, m, resp)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return T;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Hook into the catch&release dropping. When an address gets restored, we reset
|
|
||||||
# the source to allow dropping it again.
|
|
||||||
event Drop::address_restored(a: addr)
|
|
||||||
{
|
|
||||||
#Drop::debug_log(fmt("received restored for %s (scan.bro)", a));
|
|
||||||
clear_addr(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
event Drop::address_cleared(a: addr)
|
|
||||||
{
|
|
||||||
#Drop::debug_log(fmt("received cleared for %s (scan.bro)", a));
|
|
||||||
clear_addr(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
# When removing a possible scan source, we automatically delete its scanned
|
|
||||||
# hosts and ports. But we do not want the deletion propagated, because every
|
|
||||||
# peer calls the expire_function on its own (and thus applies the delete
|
|
||||||
# operation on its own table).
|
|
||||||
function remove_possible_source(s: set[addr], idx: addr): interval
|
|
||||||
{
|
|
||||||
suspend_state_updates();
|
|
||||||
delete scan_triples[idx];
|
|
||||||
resume_state_updates();
|
|
||||||
|
|
||||||
return 0 secs;
|
|
||||||
}
|
|
||||||
|
|
||||||
# To recognize whether a certain threshhold vector (e.g. report_peer_scans)
|
|
||||||
# has been transgressed, a global variable containing the next vector index
|
|
||||||
# (idx) must be incremented. This cumbersome mechanism is necessary because
|
|
||||||
# values naturally don't increment by one (e.g. replayed table merges).
|
|
||||||
function thresh_check(v: vector of count, idx: table[addr] of count,
|
|
||||||
orig: addr, n: count): bool
|
|
||||||
{
|
|
||||||
if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold )
|
|
||||||
{
|
|
||||||
ignore_addr(orig);
|
|
||||||
return F;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( idx[orig] < |v| && n >= v[idx[orig]] )
|
|
||||||
{
|
|
||||||
++idx[orig];
|
|
||||||
return T;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return F;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Same as above, except the index has a different type signature.
|
|
||||||
function thresh_check_2(v: vector of count, idx: table[addr, addr] of count,
|
|
||||||
orig: addr, resp: addr, n: count): bool
|
|
||||||
{
|
|
||||||
if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold )
|
|
||||||
{
|
|
||||||
ignore_addr(orig);
|
|
||||||
return F;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( idx[orig,resp] < |v| && n >= v[idx[orig, resp]] )
|
|
||||||
{
|
|
||||||
++idx[orig,resp];
|
|
||||||
return T;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return F;
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_established(c: connection)
|
|
||||||
{
|
|
||||||
local is_reverse_scan = (c$orig$state == TCP_INACTIVE);
|
|
||||||
Scan::check_scan(c, T, is_reverse_scan);
|
|
||||||
}
|
|
||||||
|
|
||||||
event partial_connection(c: connection)
|
|
||||||
{
|
|
||||||
Scan::check_scan(c, T, F);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_attempt(c: connection)
|
|
||||||
{
|
|
||||||
Scan::check_scan(c, F, c$orig$state == TCP_INACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_half_finished(c: connection)
|
|
||||||
{
|
|
||||||
# Half connections never were "established", so do scan-checking here.
|
|
||||||
Scan::check_scan(c, F, F);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_rejected(c: connection)
|
|
||||||
{
|
|
||||||
local is_reverse_scan = c$orig$state == TCP_RESET;
|
|
||||||
|
|
||||||
Scan::check_scan(c, F, is_reverse_scan);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_reset(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$state == TCP_INACTIVE || c$resp$state == TCP_INACTIVE )
|
|
||||||
# We never heard from one side - that looks like a scan.
|
|
||||||
Scan::check_scan(c, c$orig$size + c$resp$size > 0,
|
|
||||||
c$orig$state == TCP_INACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
event connection_pending(c: connection)
|
|
||||||
{
|
|
||||||
if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE )
|
|
||||||
Scan::check_scan(c, F, F);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Report the remaining entries in the tables.
|
|
||||||
event bro_done()
|
|
||||||
{
|
|
||||||
for ( orig in distinct_peers )
|
|
||||||
scan_summary(distinct_peers, orig);
|
|
||||||
|
|
||||||
for ( orig in distinct_ports )
|
|
||||||
port_summary(distinct_ports, orig);
|
|
||||||
|
|
||||||
for ( orig in distinct_low_ports )
|
|
||||||
lowport_summary(distinct_low_ports, orig);
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue