Friday, June 29, 2007

Rapid context switching on our User Mode Linux host

Now with hundreds of thousands of context switches per second I'm surprised that the box has any time to do any work in userland!

procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
13  0   2760  17060  15596 3767972    0    0    76   224  354 146832 30 70  0  0
10  0   2760  16944  15596 3768020    0    0    48     0  355 135414 45 55  0  0
10  0   2760  16556  15596 3768532    0    0    28     0  349 143074 37 63  0  0
9  0   2760  17380  15596 3767776    0    0    80     0  330 141158 41 59  0  0
9  1   2760  17140  15596 3767852    0    0    20     0  356 144483 39 61  0  0
9  0   2760  17152  15596 3767888    0    0    36   160  322 145730 37 63  0  0
9  0   2760  17000  15596 3768020    0    0   108     0  354 139198 38 62  0  0
6  1   2760  17660  15596 3767264    0    0    72     0  285 129292 48 52  0  0

Wednesday, June 27, 2007

Using BASE Alert Groups to deploy countermeasures to Snort alerts

For those who are familiar with the snort + BASE NIDS system...

I've cooked up a simple script that gives easily parsable output of the result of a simple SQL query that inspects already BASE Alert Groups to find the remote or local IP address, Alert Group name, number of alerts and last alert time for all hosts that have generated more that a given threshold of alerts within a given timeframe.

use strict;
use DBI;

my $time_period=24; # hours
my $event_threshold=0;
my $is_local='NOT'; # blank for local, 'NOT' for remote

my $sql=<<END;

SELECT \@A:=IF(iph.ip_src $is_local BETWEEN INET_ATON('192.168.1.0') AND INET_ATON('192.168.1.255'),iph.ip_src,iph.ip_dst) AS ip,
INET_NTOA(\@A) AS ip_f,
ag.ag_name,
MAX(e.timestamp) AS last_event,
COUNT(ag.ag_name) AS num_events
FROM acid_ag AS ag
JOIN acid_ag_alert AS aga USING (ag_id)
JOIN event AS e ON aga.ag_sid=e.sid AND aga.ag_cid=e.cid
JOIN iphdr AS iph USING (sid,cid)
WHERE e.timestamp>DATE_SUB(now(),INTERVAL ? HOUR)
GROUP BY ip, ag.ag_name
HAVING num_events>?
ORDER BY \@A

END

my $dbh=DBI->connect('DBI:mysql:snort','root');
my $sth=$dbh->prepare($sql);
$sth->execute($time_period,$event_threshold);

print "$_->{ag_name}\t$_->{ip_f}\t$_->{num_events}\t$_->{last_event}\n" while ($_=$sth->fetchrow_hashref);

$sth->finish;
$dbh->disconnect;

The output will look something like this:

banned     43.280.25.17   6       2007-06-27 16:07:27
banned     43.280.25.210  6       2007-06-27 05:46:20
botnet     147.67.18.2    2       2007-06-26 11:39:20
mailblock  147.67.18.2    1       2007-06-26 09:13:08
mailblock  217.21.112.5   2       2007-06-27 13:41:48

The remote host 147.67.18.2 has within the last 24 hours generated events that have been placed into two distinct Alert Groups: two events into "botnet" (the last event being seen 2007-06-26 11:39:20) and one event into "mailblock" at 2007-06-26 09:13:08.

This output can be parsed frequently by a number of cron scripts that deploy countermeasures against these events, e.g. block the "botnet" IP addresses at the firewall, or build zone files from "mailblock" IP addresses for local DNSBLs to filter mail from such hosts, etc...