Hi,I have created two new plugins, which I would like to share, before I go on vacation. A botnet plugin and a event tracker. The botnet plugin is a alert plugin that detects connections to know botnet controllers. The event tracker combines information from alert plugins in events and is able to display a list of them. I also addapted the Holt-Winters plugin to report to the event plugin.
The event plugin is still a bit crude and incomplete, but it is functional. It should work with either a sqlite or a mysql database although I developed with mysql so it is a bit better tested. I have included a script for both of them to create the tables. You should manually copy the plugin files to the correct directories, and create the database and use one of the scripts to create the tables for now.
The events-plugin frontend shows a paged list with events and has a filter field. This field might well be the most unintuitive field you have seen :), but I will give some helpful example filters:
Show all Holt-Winters events: "Type:[eq]holtwinters" Show all Botnet events: "Type:[eq]botnets"Show all connections to Botnet controller 192.168.1.1: "Type:[eq]botnets Destination:[eq]192.168.1.1"
The botnet plugin comes with two scripts. The first one is a cron script for retrieving botnet lists and creating the nfsen filter (as proposed by Peter in the discussion about botnets some time ago). The other is for parsing the botnet list. The idea behind this is that you can use botnet lists from different sources and different formats by editing these scripts. The provided scripts read the botnet list that Maurizio reffered to. To enable the cron script add a line to your crontab: 0 23 * * * /usr/local/bin/botnet.cron /var/lib/nfsen/botnet/bleeding-botcc.rules /var/lib/nfsen/profiles/~botnets/botnets-filter.txt
To configure them you should add these configuration options to your nfsen.conf file:
@plugins = (
[ "!", 'Events' ],
[ "!", 'Botnets' ],
[ "!", 'holt_winters' ],
);
%Pluginconf = (
holt_winters => {
profiles => [qw(traffic/smtp)],
bookmark_base => 'https://my_host/nfsen/nfsen.php',
},
events => {
db_connection_string =>
"DBI:SQLite:dbname=/var/lib/nfsen/events/events.db",
# db_connection_string =>
"DBI:mysql:database=events;host=localhost;port=3306",
# db_user => "nfsen",
# db_passwd => "very_secret",
},
botnets => {
import_cmd => "/usr/local/bin/get_botnets <
/var/lib/nfsen/botnet/bleeding-botcc.rules",
match_port => 0,
match_proto => 0,
},
);
I think this is self explanatory for the holt_winters and events
plugins. The botnet plugin requires a import_cmd, which refers to the
list-parsing script. The match_port and match_proto variables can be
used if your botnet list includes port and/or protocol information to
get more precise matches. After copying Botnets.pm you can select the
plugin in the alerts page. You can just fill in anything for the filter,
but after creating the alert, you should manually run the cron script
once, as this script updates the filter.
I hope this is useful for someone. If you would like to try it, I would really like to hear your comments, suggestions, changes and questions! I will be unavailable for questions from the 24th of August until the 19th of September.
Werner
#!/usr/bin/perl -w
#
# vim: set ts=3 sw=3:
#
# Holt-Winters Aberrant Behavior Detection plugin for NfSen
# by Gabor Kiss <[EMAIL PROTECTED]>.
# Based on work of Werner Schram <[EMAIL PROTECTED]>.
#
# Original copyright messege follows:
#
###############################################################################
# Copyright (c) 2007, SURFnet B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
copyright notice, this
# list of conditions and the following disclaimer in the
documentation and/or
# other materials provided with the distribution.
# * Neither the name of the SURFnet B.V. nor the names of its
contributors may be
# used to endorse or promote products derived from this software
without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT
# SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH
# DAMAGE.
#
###############################################################################
package holt_winters;
use strict;
use warnings;
use Time::Local;
use IO::Dir;
use MIME::Base64;
use URI::Escape;
use NfSen;
use NfConf;
use Nfcomm;
use Notification;
use Events qw(process_event);
use Sys::Syslog;
Sys::Syslog::setlogsock('unix');
our $VERSION = 130;
my $conf = $NfConf::Pluginconf{holt_winters};
my $bm_base = $conf->{bookmark_base};
sub alert_condition {
#sub run{
my ($opts) = @_;
my ($Year, $Month, $Day, $Hour, $Min) = $opts->{timeslot} =~
/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/;
my $endtime = timelocal(0, $Min, $Hour, $Day, $Month-1, $Year);
my @arguments = (
"FAILURES",
"--start", $endtime - 600, # we need exacly two rows of RRA
"--end", $endtime - 300,
);
syslog('debug', "holt_winters: timeslot: ". $opts->{timeslot}. " alert:
". $opts->{alert}. " alertfile: ". $opts->{alertfile});
my $ret = 0;
# my @mailtext;
return unless ref $conf eq 'HASH' and exists $conf->{profiles};
foreach my $profile (@{$conf->{profiles}}) {
my $alertDir = "$NfConf::PROFILEDATADIR/$profile";
syslog('err', "holt_winters: opening $alertDir"),
my $dh = IO::Dir->new($alertDir) or
syslog('err', "holt_winters: error opening $alertDir:
$!"),
return 0;
while (my $rrdfile = $dh->read) {
next unless $rrdfile =~ /\.rrd$/;
my $fullpath = "$alertDir/$rrdfile";
next unless -f $fullpath;
my ($start, $step, $dslist, $data) =
RRDs::fetch($fullpath, @arguments);
my $nameidx = 0;
foreach my $ds (@$dslist) {
my $type = $dslist->[$nameidx];
# Alert only if previous value was 0 but now it
is 1
my @failures = reverse @$data; # tricky way to
handle case of single row @$data array
#syslog('debug', "$rrdfile $ds($nameidx)
$failures[0][$nameidx]<=$failures[1][$nameidx]");
my ($bm_type, $bm_proto) = split('_', $type);
$bm_proto ||= 'any';
$bm_proto = uc($bm_proto) if $bm_proto =~ /p$/;
# TCP, UDP, ICMP
(my $bm_channel = $rrdfile) =~ s/\.rrd//;
my $bm_tend =
NfSen::ISO2UNIX($opts->{timeslot})-300;
my $bm_tleft = $bm_tend;
my $bm_tright = $bm_tend;
my $bm_profile =
($profile=~/\//)?$profile:"./$profile";
if ($failures[0][$nameidx] and
!$failures[1][$nameidx]) { # mark the beginning of the abberant behavior
syslog('debug', "holt_winters: found
abberant behavior in rrd: $fullpath in RRA $type");
# my $bookmark = join('|',
# 2,'-',"./$profile",
#
$bm_channel,$bm_proto,$bm_type,1,1,
# $bm_tend,$bm_tleft,$bm_tright,
# 0,1,0
# );
# syslog("debug",join('|', $bookmark));
# $bookmark=encode_base64($bookmark);
# $bookmark=~s/\n//gs;
# $bookmark=uri_escape($bookmark);
# push(@mailtext,
# "$bm_profile $rrdfile $type
$opts->{timeslot}\n",
# "$bm_base?bookmark=$bookmark\n",
# "\n"
# );
Events::process_event({
"StartTime"=>$bm_tend,
"Type"=>"holtwinters",
"Level"=>"notify",
"Profile"=>$bm_profile,
"Channel"=>$bm_channel,
"Graph"=>$bm_type,
"Proto"=>$bm_proto,
});
$ret = 1;
} elsif ($failures[1][$nameidx] and
!$failures[0][$nameidx]) { # mark the end of the abberant behavior
Events::process_event({
"Type"=>"[eq]holtwinters",
"Level"=>"[eq]notify",
"Profile"=>"[eq]".$bm_profile,
"Channel"=>"[eq]".$bm_channel,
"Graph"=>"[eq]".$bm_type,
"Proto"=>"[eq]".$bm_proto,
"StopTime"=>["[eq]NULL",$bm_tend],
});
}
$nameidx++;
}
}
$dh->close;
}
# $ret and notify("Holt-Winters alert", [EMAIL PROTECTED]);
return $ret;
}
sub Init {
syslog('debug', "holt_winters: init");
# my $list=get_event_ids({
# "Type"=>"[eq]holtwinter",
# "Level"=>"[eq]notify",
# });
# syslog('debug',"Event: ".join(',',@$list));
return 1;
}
1;
# vi: ts=3 sw=3
nfsen-events.tar.gz
Description: GNU Zip compressed data
nfsen-botnet.tar.gz
Description: GNU Zip compressed data
------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________ Nfsen-discuss mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/nfsen-discuss
