In many networks, the types of network services offered by internal hosts tend to be rather stable over time. If a system suddenly starts running a new service (i.e., accepts connections on a port it did not before), this can be a noteworthy event by itself. In this exercise we will write a Bro script which tracks the services offered by local hosts over time and generates a notice when a new one pops up.
Write a script which for every local host remembers the destination
ports of all incoming, fully established connections. Generate a notice
whenever a host accepts a connection for the first time on a
specific port. Run the script on the trace
enterprise-1.trace. Assume that all hosts in
128.3.0.0/16 and 131.243.0.0/16
are internal, and all others are external.
Make the detection a bit more customizable:
How would you set these options for the traffic in
enterprise-1.trace?
Extend the script to keep the collected port information across restarts. Run first with enterprise-1.trace and then with enterprise-2.trace. How many tuples (host,port) has Bro remembered after running on the first trace, how many after running on both?
If run for the first time, the script reports lots of services because it does not have any previous knowledge about the network. Add a learning mode which, when activated, builds the service profile but does not generate any notice.
Extend the script to print a summary of remembered (host, port) tuples when Bro terminates.
Events which might be of use to solve this:
event connection_established(c: connection)
# Raised whenever Bro sees a fully established connection.
event bro_done()
# Raised just before the Bro process terminates.
Some syntax hints:
- Check for privileged port:
if ( p >= 1024/tcp ) ...
- Insert element into set:
add services[1.2.3.4, 25/tcp];
- Check whether element is in set:
if ( [1.2.3.4, 25/tcp] in services ) ...
Because the traces contain only headers, add this to suppress warnings
about missing payload:
@load weird
redef notice_action_filters += {
[ContentGap] = ignore_notice
};
redef notice_policy += {
[$pred(a: notice_info) = {
return a$note == WeirdActivity &&
("incompletely_captured_fragment" in a$msg ||
"UDP_datagram_length_mismatch" in a$msg);
},
$result = NOTICE_IGNORE]
};