Sep 2010
Snort Intrusion Detection Software (IDS) is a great out of the box easy to use system to monitor a network for possible threats. While there are many ways to receive alerts, one very simple approach is to periodically parse the alert log and simply mail alerts to whom it may concern. In this text a simple example of parsing a snort alert log using Perl. Note this alerter could probably be used for other loggers and there exist other tools available like Splunk which might be more suited for larger installations. The thesis of this text is to show how a relatively useful utility can be quickly hacked together to provide an elegant solution.
Since this text has the time to think logically (the author didn't) here is some pseudo code that expresses the idea of how this particular parser will work. For the time being the script is interested in priority 1 and priority 2 alerts:
Read the alert log into an array loop over alert log priority 2 alert? if yes, start appending lines temp file until \ next alert entry priority 1 alert? if yes, start appending lines temp file until \ next alert entry end loop alert log did we find alerts? yes stop snort backup the alert file start snort mail tmp file delete tmp file no exit program
Sure seems simple enough. Of course there is more to it. First up the helper subroutines. Only one is needed since the only repeated operation that is being performed is (possibly) appending alert log lines to a temporary file that will be mailed to the administrator:
sub appendfile {
my ($fp, $msg) = @_;
if (open(FILE, ">>$fp")) {
print FILE ("$msg");
close FILE;
} else {
die ("Could not open $fp!");
}
}
With the one subroutine complete now a look at the variables the script will need:
my $logdir = "/var/log/snort"; my $logfile = "alert"; my $msgfile = "/var/tmp/snort-alerts.$$";
Now setup some more variables and get everything set for the loop:
open(FILE, "$logdir/$logfile");
my @alerts = <FILE>;
close FILE;
if (scalar(@alerts) == 0) { exit (0); } # exit if there are 0 entries
my $do_msg = 0; # if we have not hit another record keep appending lines
my $pri2 = 0; # A count of pri 2 alerts
my $pri1 = 0; # A count of pri 1 alerts
Now the script is ready to enter the core algorithm, looking for trouble.
This is accomplished using a foreach loop over each line
of the alerts array, then pattern matching each line. If a match is
found set the do_msg flag to 1. The script will append
lines to the message file until it sees the next message. Once the script
sees a new message, it resets do_msg to 0. Rinse and repeat
as needed:
foreach (@alerts) {
# if we hit a new record reset the message logger
if (/\[\*\*/) {
$do_msg = 0;
}
# if we have still not hit a new record keep appending lines to msg file
if ($do_msg eq 1) {
appendfile($msgfile, $_);
}
# if we hit a Pri2 or 1 increment counter, append the line to msg file
# and set the flag to keep appending lines until we hit the next
# new alert record
if (/Priority: 2/) {
appendfile($msgfile, $_);
$pri2++;
$do_msg = 1;
}
if (/Priority: 1/) {
appendfile($msgfile, $_);
$pri1++;
$do_msg = 1;
}
}
Now that the decision and data collecting portion is done it is time to
decide what to do (if anything) with the results. The
pri1 and pri2 variables are added and checked, if
the result is anything greater than zero the script:
The last step deletes the message file. Note that the reason a system command is used to mail the message is to not rely upon Perl modules. If one were inclined, they could use Perl modules for the mail operation and init script:
# if we have either pri1 or 2 alerts, finish the message file and mail it out
if ($pri1 + $pri2) {
my $date = `date +%F-%H%M-%S`;
system("/etc/init.d/snortd stop");
chdir ($logdir);
rename($logfile, $logfile.$date);
system("/etc/init.d/snortd start");
appendfile($msgfile, "Pri 1 alerts: $pri1\n");
appendfile($msgfile, "Pri 2 alerts: $pri2\n");
system("/bin/cat $msgfile | /bin/mail -s Snort-Alerts me\@mail.domain.org");
}
unlink($msgfile); # delete the temp message file
Following is what an alert that is emailed would look like:
From: snort@somesensor.net To: cooladmin@roxor.net Cc: Subj: Snort-Alerts [**] [1:2049:6] SQL ping attempt [**] [Classification: Misc activity] [Priority: 2] 08/03-12:38:47.049614 192.168.48.68:1575 -> 255.255.255.255:1434 UDP TTL:128 TOS:0x0 ID:27143 IpLen:20 DgmLen:29 Len: 1 [Xref => http://cgi.nessus.org/plugins/dump.php3?id=10674]