From 5b262f7949f3e8b28c3776c4238c5eec81be3fe3 Mon Sep 17 00:00:00 2001 From: Jakub Cegan <cegan@ics.muni.cz> Date: Tue, 19 Mar 2013 20:11:50 +0100 Subject: [PATCH] Task #613 jednoduche cmd * pridal jsem dva prepinace * -c pro konfiguracni soubor i s cestou * -i pro interval ve dnech pro dotazy (napr. jak dlouho je klient neaktivni) * uklid neporadku v contrib --- .../networkReporter-client/networkReporter.pl | 175 ----------- src/contrib/wardenWatchdog.pl | 271 ------------------ src/contrib/wardenWatchdog.t | 71 ----- 3 files changed, 517 deletions(-) delete mode 100755 src/contrib/networkReporter-client/networkReporter.pl delete mode 100755 src/contrib/wardenWatchdog.pl delete mode 100644 src/contrib/wardenWatchdog.t diff --git a/src/contrib/networkReporter-client/networkReporter.pl b/src/contrib/networkReporter-client/networkReporter.pl deleted file mode 100755 index ed32b7d..0000000 --- a/src/contrib/networkReporter-client/networkReporter.pl +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/perl -# -# networkReporter.pl - Warden client for communication with RT ticketing system -# -# Copyright (C) 2012 Masaryk University -# Author(s): Jakub CEGAN <cegan@ics.muni.cz> -# -# 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 Masaryk University 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. -# - -use warnings; -use strict; - -use lib '/opt/warden-client'; -use Email::Simple; -use Sys::Hostname; -use Text::Wrap; -use DateTime; - - -sub sendmailWrapper{ - my $message = shift; - - if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ - print $sendmail $message; - close $sendmail; - return 1; - } else { - return (0, "Sending email failed: $!"); - } -} - -sub timeToLocal{ - my $time = shift; - - my ($y,$m,$d,$h,$mm,$s); - if(!($$time =~ m/(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})/)){ - return (0, "Bad time format!\n"); - } - - ($y,$m,$d,$h,$mm,$s) = $$time =~ m/(\d{4})\-(\d{2})\-(\d{2})\ (\d{2})\:(\d{2})\:(\d{2})/; - eval{ - my $dt = DateTime->new( - year => $y, - month => $m, - day => $d, - hour => $h, - minute => $mm, - second => $s, - time_zone =>'gmt'); - $dt->set_time_zone('local'); - $$time = $dt->strftime('%d. %m. %Y v %H:%M');}; - if($@){ - return (0, "Can't convert time to epoch format!\n"); - } - return 1; -} - -#------------------------------------------------------------------------------- -# reportToRT - fuction for creating tickets in the RT system -# -# param: hash with gateway address and warden event array -# -# return: ok || fail -#------------------------------------------------------------------------------- -sub reportToRT{ - - my $inputData = shift; - my $toGateway = $$inputData{'gateway'}; - my @event = @{$$inputData{'data'}}; - - my $fromHostname; - my $message; - my ($rc, $err); - - if(!($toGateway)){ - return (0, "Empty 'To' email header!\n"); - } - - eval{ - $fromHostname = hostname(); - if(!($fromHostname =~ m/\.ics\.muni\.cz/gi)){ - $fromHostname .= '.ics.muni.cz'; - } - }; - if($@){ - return (0, "Can't retrive hostname for 'From' header!\n"); - } - - ($rc, $err) = timeToLocal(\$event[3]); - if(!$rc){ - return (0, $err); - } - - my $text = "Dobrý den, - z VaÅ¡Ã IP adresy $event[6] jsme zaznamenali $event[3] celkem $event[9] pokus(y) o pÅ™ipojenà k neexistujÃcà službÄ› (tzv. honeypotu). V tomto konkrétnÃm pÅ™ÃpadÄ› se jednalo o protokol $event[7] a port ÄÃslo $event[8]. Je pravdÄ›podobné, že se jedná o virus, napadený poÄÃtaÄ Äi zneužitý uživatelský úÄet. DoporuÄujeme Vám zkontrolovat zabezpeÄenà tohoto poÄitaÄe. - - S pozdravem - - CSIRT-MU - http://www.muni.cz/csirt"; - - eval{ - $message = Email::Simple->create( - header => [ - To => $toGateway, - From => 'tools@'.$fromHostname, - Subject => 'Pristup na honeypot v siti CESNET'], - body => fill('','',$text)); - }; - if($@){ - return (0, "Can't create email message\n"); - } - - ($rc, $err) = sendmailWrapper($message->as_string); - if(!$rc){ - return (0, $err); - } - return 1; -} - - -my $warden_path = '/opt/warden-client'; - -require $warden_path . '/lib/WardenClientReceive.pm'; - -my $requested_type = "portscan"; -my $ip_reg = '147\.251\.\d+\.\d+'; -my $client = 'CESNET_IDS'; -my $gateway = 'rt@rt-devel.ics.muni.cz'; - -$Text::Wrap::columns = 90; - - -my $logger; -my @new_events; - -@new_events = WardenClientReceive::getNewEvents($warden_path, $requested_type); -#@new_events = (["5179620","au1.cesnet.cz","CESNET_IDS","2012-11-08 17:04:56","portscan","IP","147.251.216.8","XXX","666","2","","0","720"]); -foreach (@new_events) { - my @event = @$_; - - if(($event[6] =~ /^$ip_reg$/i) and ($event[2] =~ /^$client$/i)){ - my %input = (gateway => $gateway, data => \@event); - my ($rc,$err) = reportToRT(\%input); - if(!$rc){ - #print "ERR: $err\n"; - syslog("err|Warden client - networkReporter $err\n"); - } - } -} - -exit 0; diff --git a/src/contrib/wardenWatchdog.pl b/src/contrib/wardenWatchdog.pl deleted file mode 100755 index 001a169..0000000 --- a/src/contrib/wardenWatchdog.pl +++ /dev/null @@ -1,271 +0,0 @@ -#!/usr/bin/perl -# -# WardenWatchdog.pl -# -# Copyright (C) 2011-2012 Cesnet z.s.p.o -# -# Use of this source is governed by a BSD-style license, see LICENSE file. - - -#use WardenConf; -use strict; -use warnings; -use DBI; -use DBD::mysql; -use DateTime; -use Email::Simple; -use Sys::Hostname; -use Data::Dumper; - -sub sendmail_wrapper{ - my $message = shift; - if(open(my $sendmail, '|/usr/sbin/sendmail -oi -t')){ - print $sendmail $message; - close $sendmail; - return 1; - } else { - return (0, "Sending email failed: $!"); - } -} - -# Array of hashes -#{query => ; text => ; contact => } - -sub send_report{ - - my $input_data = shift; - my $contact = $$input_data{'contact'}; - my $domain = $$input_data{'domain'}; - my $text = $$input_data{'text'}; - - my $from_hostname; - my $message; - - if(!($contact)){ - return (0, "Empty 'To' email header!\n"); - } - - $domain =~ s/\./\./; - eval{ - $from_hostname = hostname(); - if(!($from_hostname =~ m/^$domain$/gi)){ - $from_hostname = $domain; - } - 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 warden serveru na stroji $domain"], - body => $text); - } or do { - return (0, "Can't create email message\n"); - }; - - my ($rc, $err) = sendmail_wrapper($message->as_string); - if(!$rc){ - return (0, $err); - } - return 1; -} - -sub connect_to_DB { - - my $dbPlatform = 'mysql'; - my $dbName = 'warden'; - my $dbHostname = 'localhost'; - my $dbUser = 'root'; - my $dbPasswd = 'w4rd3n&r00t'; - - my $dbhRef = shift; - my $dbh; - - if($dbh = DBI->connect( "dbi:$dbPlatform:database=$dbName;host=$dbHostname", $dbUser, $dbPasswd, {RaiseError => 1, mysql_auto_reconnect => 1})){ - $$dbhRef = $dbh; - return 1; - } - else{ - return (0,"Cannot connect to database! ".DBI->errstr); - } -} - - -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; - - my @config = @{$configRef}; - my %bad_events; - my ($rc,$err); - my $dbh; - - my $i = 0; - # connect to DB - ($rc,$err) = connect_to_DB(\$dbh); - if (!$rc){ - return (0,'send_query can\'t connect do DB: '.$err); - } - - while ($i < scalar(@config)) { - # run DB query -> requestor, client name - my $sth; - if (defined($config[$i]{query})){ - $sth = $dbh->prepare($config[$i]{query}); - } - else{ - return (0, "No query availble\n"); - } - - if (!($sth->execute)){ - return (0, "Couldn't get data from my database: $sth->errstr\n"); - }; - - 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"; - } - } - foreach my $key (keys %bad_events){ - $bad_events{$key} .= "\n\n"; - } - - $sth->finish; - $i++; - } - # disconnect to DB - $dbh->disconnect; - - %$eventsRef = %bad_events; - - return 1; -} - - -sub run{ - - my $domain = shift; - my $period = shift; - - my $date; - - eval{ - 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"); - }; - - # 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 => "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) = send_query(\@configuration,\%bad_events); - if (!$rc){ - #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) = send_report(\%input); - if (!$rc){ - #print $err; - syslog("err|Warden client - networkReporter $err\n"); - } - } -} - -run('warden-dev.cesnet.cz',7); -1; diff --git a/src/contrib/wardenWatchdog.t b/src/contrib/wardenWatchdog.t deleted file mode 100644 index 3ab8d87..0000000 --- a/src/contrib/wardenWatchdog.t +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use DBI; -use DBD::mysql; -use Data::Dumper; - -use Test::More tests => 7; -use Test::MockModule; -use Test::Exception; - -use lib '..'; -use wardenWatchdog; - - -my (%input, $retCode, $result); - -print "== wardenWatchdog::send_report ==\n"; - -*wardenWatchdog::sendmail_wrapper = sub {print "sendmailWrapper is set to broken!\nSending of emails will fail\n"; return 0;}; - -%input = (contact => 'test@test.receiver.cz', domain => 'test.domain.cz', text => 'TEST MSG!'); -($retCode, $result) = wardenWatchdog::send_report(\%input); -ok ($retCode == 0, 'Broken sendmail'); - -*wardenWatchdog::sendmail_wrapper = sub {print "sendmailWrapper is OFF!\nSending of emails is blocked\n"; return 1;}; - -%input = (contact => '', domain => 'test.domain.cz', text => 'TEST MSG!'); -($retCode, $result) = wardenWatchdog::send_report(\%input); -ok ($retCode == 0, 'No contact'); - -%input = (contact => 'test@test.receiver.cz', domain => '', text => 'TEST MSG!'); -($retCode, $result) = wardenWatchdog::send_report(\%input); -ok ($retCode == 0, 'No domain'); - -%input = (contact => '', domain => 'test.domain.cz', text => ''); -($retCode, $result) = wardenWatchdog::send_report(\%input); -ok ($retCode == 0, 'No text'); - -%input = (contact => 'test@test.receiver.cz', domain => 'test.domain.cz', text => 'TEST MSG!'); -($retCode, $result) = wardenWatchdog::send_report(\%input); -ok ($retCode == 1, 'All OK'); - -print "== wardenWatchdog::connect_to_DB ==\n"; -my $dbh; -($retCode, $result) = connect_to_DB(\$dbh); -ok ($retCode == 1, 'Connected to the DB'); - -# FAILED DB CONNECTION - -print "== wardenWatchdog::update_procedures ==\n"; - -# CORRECT RUN OF update_procedures - -print "== wardenWatchdog::send_query ==\n"; - -# RUN WITH BROKEN DB CONNECTION - -# RUN WITH NO query - -# CORRECT RUN OF send_query - -print "== wardenWatchdog::run ==\n"; - -# RUN WITHOUT domain - -# RUN WITHOUT period - -# CORRECT RUN OF send_query -- GitLab