From 8166912cdd6a5510550917bd1351b9636ab3356e Mon Sep 17 00:00:00 2001 From: Jakub Cegan <cegan@ics.muni.cz> Date: Thu, 24 Jan 2013 09:14:11 +0100 Subject: [PATCH] (task #613) Warden Watchdog - 1. funkcni verze Prvni funkcni verze kontroly klientu a udalosti v databazi. Staci nastavit v cronu a provadi predchystane kontroly a reportuje na zadane emaily. --- src/warden-server/bin/wardenWatchdog.pl | 156 +++++++++++++++++------- 1 file changed, 110 insertions(+), 46 deletions(-) diff --git a/src/warden-server/bin/wardenWatchdog.pl b/src/warden-server/bin/wardenWatchdog.pl index 0c02581..001a169 100755 --- a/src/warden-server/bin/wardenWatchdog.pl +++ b/src/warden-server/bin/wardenWatchdog.pl @@ -7,20 +7,18 @@ # Use of this source is governed by a BSD-style license, see LICENSE file. -use WardenConf; +#use WardenConf; use strict; use warnings; use DBI; use DBD::mysql; use DateTime; -#use Email::Simple; +use Email::Simple; use Sys::Hostname; -use Text::Wrap; use Data::Dumper; -sub sendmailWrapper{ +sub sendmail_wrapper{ my $message = shift; - if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ print $sendmail $message; close $sendmail; @@ -33,8 +31,7 @@ sub sendmailWrapper{ # Array of hashes #{query => ; text => ; contact => } -# Get clients admins -sub sendReport{ +sub send_report{ my $input_data = shift; my $contact = $$input_data{'contact'}; @@ -49,31 +46,28 @@ sub sendReport{ } $domain =~ s/\./\./; - eval{ $from_hostname = hostname(); - if(!($from_hostname =~ m/$domain/gi)){ - $from_hostname .= $domain; + if(!($from_hostname =~ m/^$domain$/gi)){ + $from_hostname = $domain; } - }; - if($@){ + 1; + } or do { return (0, "Can't retrive hostname for 'From' header!\n"); - } + }; eval{ - #$message = Email::Simple->create( - #header => [ - #To => $contact, - #From => 'warden_watchdog@'.$from_hostname, - #Subject => 'Kotrola stavu udalosti na Wardenu'], - #body => fill('','',$text)); - }; - if($@){ + $message = Email::Simple->create( + header => [ + To => $contact, + From => 'warden_watchdog@'.$from_hostname, + Subject => "Kotrola stavu udalosti warden serveru na stroji $domain"], + body => $text); + } or do { return (0, "Can't create email message\n"); - } + }; - print "== $contact ==\n$text\n"; - my ($rc, $err) = 1;#sendmailWrapper($message->as_string); + my ($rc, $err) = sendmail_wrapper($message->as_string); if(!$rc){ return (0, $err); } @@ -100,7 +94,32 @@ sub connect_to_DB { } } -sub sendQuery{ + +sub update_procedures{ + + my $procRef = shift; + + my @procedures = @{$procRef}; + my $dbh; + + # connect to DB + my ($rc,$err) = connect_to_DB(\$dbh); + if (!$rc){ + return (0,'update_procedures can\'t connect do DB: '.$err); + } + + foreach my $proc (@procedures) { + $dbh->do($proc); + } + + # disconnect to DB + $dbh->disconnect; + + return 1; +} + + +sub send_query{ my $configRef = shift; my $eventsRef = shift; @@ -114,12 +133,10 @@ sub sendQuery{ # connect to DB ($rc,$err) = connect_to_DB(\$dbh); if (!$rc){ - return (0, $err); + return (0,'send_query can\'t connect do DB: '.$err); } while ($i < scalar(@config)) { - my $contact; - # run DB query -> requestor, client name my $sth; if (defined($config[$i]{query})){ @@ -134,15 +151,27 @@ sub sendQuery{ }; my @result; + my $contact; + my $msg_text = 1; while(@result = $sth->fetchrow()){ if (defined($config[$i]{contact})){ $contact = $config[$i]{contact}; + if($msg_text){ + $bad_events{$contact} .= $config[$i]{text} . "\n\n"; + $msg_text = 0; + } + $bad_events{$contact} .= join(", ",@result) . "\n"; } else{ $contact = "from_db\@$result[0]"; + $bad_events{$contact} .= $config[$i]{text} . "\n\n"; + $bad_events{$contact} .= join(", ",@result) . "\n"; } - $bad_events{$contact} .= $config[$i]{text} . "DB INFO: ". join(', ',@result) ."\n"; } + foreach my $key (keys %bad_events){ + $bad_events{$key} .= "\n\n"; + } + $sth->finish; $i++; } @@ -166,40 +195,75 @@ sub run{ my $dt = DateTime->now(); $dt = DateTime->now()->subtract(days => $period); $date = $dt->date(); + } or do { + #print "Warden watchdog - can't work with date\n"; + syslog("err|Warden watchdog - can't work with date\n"); }; - if($@){ - print "Warden watchdog - can't work with date\n"; - #syslog("err|Warden watchdog - can't work with date\n"); - } + # stored procedures + # iptest - is ip from private network + + my @procedures = ('DROP FUNCTION IF EXISTS iptest;', 'CREATE FUNCTION iptest(ip VARCHAR(15)) RETURNS TINYINT(1) DETERMINISTIC +BEGIN + SET @nip = INET_ATON(ip); + IF( + ISNULL( @nip) OR + @nip BETWEEN 0 AND 16777216 OR + @nip BETWEEN 167772160 AND 171966464 OR + @nip BETWEEN 2130706432 AND 2130706433 OR + @nip BETWEEN 2851995648 AND 2851995649 OR + @nip BETWEEN 2886729728 AND 2886729729 OR + @nip BETWEEN 3221225472 AND 3221225473 OR + @nip BETWEEN 3221225984 AND 3221225985 OR + @nip BETWEEN 3227017984 AND 3227017985 OR + @nip BETWEEN 3232235520 AND 3232235521 OR + @nip BETWEEN 3323068416 AND 3323068417 OR + @nip BETWEEN 3325256704 AND 3325256705 OR + @nip BETWEEN 3405803776 AND 3405803777 OR + @nip BETWEEN 3758096384 AND 3758096385 OR + @nip BETWEEN 4026531840 AND 4026531841 OR + @nip > 4294967295) THEN + RETURN TRUE; + ELSE + RETURN FALSE; + END IF; +END;'); + + # {query => ; text => ; contact => } + # Time of last event of each client. + # Is it unsupported type of event? + # Is event from the future? + # Martane - Is IP from the private network? my @configuration = ( - {query => "SELECT hostname, service, MAX(received) FROM events WHERE valid = 't' GROUP BY hostname, service ORDER BY MAX(received) ASC;", text => "Hey, this is test of warning for admin!\n"}, - {query => "SELECT requestor FROM clients WHERE service IN (SELECT service FROM events WHERE detected > '$date' AND type NOT IN ('portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other') AND valid = 't' GROUP BY service) GROUP BY requestor;", text => "Hey, this is test of warning!\n", contact => 'warden-administrator@cesnet.cz'}); - - $Text::Wrap::columns = 80; + {query => "SELECT hostname, service, MAX(received) FROM events WHERE valid = 't' GROUP BY hostname, service ORDER BY MAX(received) ASC;", text => "Uvedeny klient, nebo klienti jiz delsi dobu nereportovali zadne udalosti do Wardenu. Je mozne, ze nefunguji spravne.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT requestor FROM clients WHERE service IN (SELECT service FROM events WHERE detected > '$date' AND type NOT IN ('portscan', 'bruteforce', 'probe', 'spam', 'phishing', 'botnet_c_c', 'dos', 'malware', 'copyright', 'webattack', 'test', 'other') AND valid = 't' GROUP BY service) GROUP BY requestor;", text => "Uvedeny klient, nebo klienti zasilaji nepodporovany nebo zastaraly typ udalosti na server Warden", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT hostname, service, type, COUNT(*) FROM events WHERE detected - received > 0 AND received > '$date' GROUP BY hostname, service, type;", text => "Uvedeny klient, nebo klienti odesilaji odesilaji udalosti s casem z budoucnosti. Cas prirazeny serverem pri prichodu udalosti (received) musi byt vzdy roven nebo vetsi casu detekce (detected).", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}, + {query => "SELECT hostname, service, received, source, count(source) AS c, min(received), max(received) FROM events WHERE valid = 't' AND source_type = 'IP' AND iptest(source) GROUP BY hostname, service, source ORDER BY c DESC;", text => "Uvedeni klient, nebo klienti odesilaji udalosti se zdrojovou adresou, ktera by se nemela objevit v internetu (privatni rozsah), nebo je neplatna (prazdny oktet, oktet je vetsi nez 255, apod.). kvuli omezeni verzi MySQL serveru funguje zatim pouze pro IPv6.", contact => 'jakubcegan@cesnet.cz, ph@cesnet.cz'}); + my ($rc,$err) = update_procedures(\@procedures); + if (!$rc){ + #print "Warden watchdog - $err\n"; + syslog("err|Warden watchdog - $err\n"); + } my %bad_events; - my $i = 0; while ($i < scalar(@configuration)) { - my ($rc,$err) = sendQuery(\@configuration,\%bad_events); + my ($rc,$err) = send_query(\@configuration,\%bad_events); if (!$rc){ - print "Warden watchdog - $err\n"; - #syslog("err|Warden watchdog - $err\n"); + #print "Warden watchdog - $err\n"; + syslog("err|Warden watchdog - $err\n"); } $i++; } while (my ($contact, $text) = each(%bad_events)){ my %input = (contact => $contact, domain => $domain, text => $text); - my ($rc,$err) = sendReport(\%input); + my ($rc,$err) = send_report(\%input); if (!$rc){ - # TODO syslog - print $err; - #syslog("err|Warden client - networkReporter $err\n"); + #print $err; + syslog("err|Warden client - networkReporter $err\n"); } - print "\n\n"; } } -- GitLab