From ac58da12e15fe2f3028010ca72e98a97bfe63d15 Mon Sep 17 00:00:00 2001 From: Tomas Plesnik <plesnik@ics.muni.cz> Date: Thu, 9 Aug 2012 16:58:30 +0200 Subject: [PATCH] pridana podpora pro validaci typu prichozich udalosti + doplnen install.sh --- src/warden-server/etc/warden-server.conf | 9 +- src/warden-server/lib/Warden.pm | 105 ++++++++++++++--------- src/warden-server/sh/install.sh | 9 +- 3 files changed, 81 insertions(+), 42 deletions(-) diff --git a/src/warden-server/etc/warden-server.conf b/src/warden-server/etc/warden-server.conf index f7ed950..5a99105 100644 --- a/src/warden-server/etc/warden-server.conf +++ b/src/warden-server/etc/warden-server.conf @@ -34,6 +34,13 @@ $DB_HOST = "localhost"; #------------------------------------------------------------------------------- # MAX_EVENT_LIMIT - maximum number of events that can be downloaded from -# Warden server in a single getNewEvents client function call +# Warden server in a single getNewEvents client function call #------------------------------------------------------------------------------- $MAX_EVENT_LIMIT = "1000000"; + +#------------------------------------------------------------------------------- +# VALID_STRINGS - validation hash containing allowed event attributes +#------------------------------------------------------------------------------- +%VALID_STRINGS = ( +"type" => ["portscan", "bruteforce", "spam", "phishing", "botnet_c_c", "dos", "malware", "copyright", "webattack", "test", "other", "_any_"], +); diff --git a/src/warden-server/lib/Warden.pm b/src/warden-server/lib/Warden.pm index 842ca30..a3e0fe5 100755 --- a/src/warden-server/lib/Warden.pm +++ b/src/warden-server/lib/Warden.pm @@ -19,6 +19,7 @@ use Net::CIDR::Lite; use DateTime; use MIME::Base64; use Crypt::X509; +use List::Util 'first'; our $VERSION = "2.1"; @@ -33,7 +34,8 @@ our $DB_NAME = undef; our $DB_USER = undef; our $DB_PASS = undef; our $DB_HOST = undef; -our $MAX_EVENT_LIMIT = undef; +our $MAX_EVENT_LIMIT = undef; +our %VALID_STRINGS = undef; # read config file if (!open( TMP, $conf_file)) { @@ -164,14 +166,14 @@ sub authorizeClient # check if client is registered if ($sth->rows == 0) { - write2log ("err", "Unauthorized access to $function_name from: $ip (CN(AN): $alt_names), used service '$service_type' - client is not registered"); + write2log ("err", "Unauthorized access to $function_name from: $ip; CN(AN): $alt_names; used service: '$service_type' - client is not registered"); die("Access denied - client is not registered at warden server!"); return undef; } # check if client has IP from registered CIDR if (!$correct_ip_source) { - write2log ("err", "Unauthorized access to $function_name from: $ip (CN(AN): $alt_names), used service '$service_type' - access from bad subnet: Registered subnet '" . $ret{'cidr'} . "'"); + write2log ("err", "Unauthorized access to $function_name from: $ip; CN(AN): $alt_names; used service: '$service_type' - access from bad subnet: Registered subnet '" . $ret{'cidr'} . "'"); die("Access denied - access from unauthorized subnet!"); return undef; } @@ -198,8 +200,9 @@ sub saveNewEvent my $ip = $ENV{'REMOTE_ADDR'}; # variables defined by server - my $client_type = "s"; # incoming client MUST be sender - my $valid = "t"; # registered sender has valid events + my $function_name = 'saveNewEvent'; + my $client_type = 's'; # incoming client MUST be sender + my $valid = 't'; # registered sender has valid events my $received = DateTime->now; # time of event delivery (UTC) # parse object (event) parameters @@ -215,13 +218,22 @@ sub saveNewEvent my $priority = $data->{'PRIORITY'}; my $timeout = $data->{'TIMEOUT'}; - my %client = authorizeClient($alt_names, $ip, $service, $client_type, 'saveNewEvent'); + my %client = authorizeClient($alt_names, $ip, $service, $client_type, $function_name); if(defined %client) { - # insert new events into DB - $sth=$DBH->prepare("INSERT INTO events VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); - if (!defined $sth) { die("Cannot do insert statement in saveNewEvent: $DBI::errstr\n") } - $sth->execute(undef, $client{'dns'}, $service, $detected, $received, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $valid); - return 1; + + # check validity of event attributes - TYPE + my $valid_types_ref = $VALID_STRINGS{'type'}; + my @valid_types = @$valid_types_ref; + my $match = first { /$type/ } @valid_types; + if ($match) { + $sth=$DBH->prepare("INSERT INTO events VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"); + if (!defined $sth) { die("Cannot do insert statement in $function_name: $DBI::errstr\n") } + $sth->execute(undef, $client{'dns'}, $service, $detected, $received, $type, $source_type, $source, $target_proto, $target_port, $attack_scale, $note, $priority, $timeout, $valid); + return 1; + } else { + write2log ("err", "Unknown event type - client from: $ip; CN(AN): $alt_names; used type: '$type'"); + die("Unknown event type - client sent event with unknown type '$type'!"); + } } } # END of saveNewEvent @@ -239,34 +251,36 @@ sub getNewEvents my $cn = $ENV{'SSL_CLIENT_S_DN_CN'}; my $alt_names = getAltNames(undef); my $ip = $ENV{'REMOTE_ADDR'}; - my $client_type = "r"; # incoming client MUST be sender + + my $client_type = 'r'; # incoming client MUST be sender + my $function_name = 'getNewEvents'; # parse SOAP data object my $requested_type = $data->{'REQUESTED_TYPE'}; my $last_id = $data->{'LAST_ID'}; - my %client = authorizeClient($alt_names, $ip, $requested_type, $client_type, 'getNewEvents'); + my %client = authorizeClient($alt_names, $ip, $requested_type, $client_type, $function_name); if(defined %client) { if ($client{'receive_own'} eq 't') { # check if client want your own events or not if ($requested_type eq '_any_') { # check if client want each or only one type of messages $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND valid = 't' ORDER BY id ASC limit $MAX_EVENT_LIMIT;"); - if (!defined $sth) {die("Cannot prepare ROE-ANY statement in getNewEvents: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare ROE-ANY statement in $function_name: $DBI::errstr\n")} $sth->execute($last_id); } else { $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' ORDER BY id ASC limit $MAX_EVENT_LIMIT;"); - if (!defined $sth) {die("Cannot prepare ROE statement in getNewEvents: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare ROE statement in $function_name: $DBI::errstr\n")} $sth->execute($last_id, $requested_type); } } else { if ($requested_type eq '_any_') { $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND valid = 't' AND hostname NOT LIKE ? ORDER BY id ASC limit $MAX_EVENT_LIMIT;"); - if (!defined $sth) {die("Cannot prepare ANY statement in getNewEvents: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare ANY statement in $function_name: $DBI::errstr\n")} my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; $domain = '\%' . $domain; $sth->execute($last_id, $domain); } else { $sth = $DBH->prepare("SELECT * FROM events WHERE type != 'test' AND id > ? AND type = ? AND valid = 't' AND hostname NOT LIKE ? ORDER BY id ASC limit $MAX_EVENT_LIMIT;"); - if (!defined $sth) {die("Cannot prepare statement in getNewEvents: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare statement in $function_name: $DBI::errstr\n")} my ($domain) = $cn =~ /([^\.]+\.[^\.]+)$/; $domain = '\%' . $domain; $sth->execute($last_id, $requested_type, $domain); @@ -328,9 +342,10 @@ sub getNewEvents sub getLastId { my ($class, $arg) = @_; + my $function_name = 'getLastId'; my $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if ( !defined $sth ) { die("Cannot prepare statement in getLastId: $DBI::errstr\n") } + if ( !defined $sth ) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $result = $sth->fetchrow(); @@ -351,8 +366,10 @@ sub registerSender my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'registerSender'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to registerSender from: $ip ($cn) - access allowed only from localhost"); + write2log ("err", "Unauthorized access to $function_name from: $ip ($cn) - access allowed only from localhost"); die("Access denied - access allowed only from localhost!"); } else { # defined variables by method @@ -370,7 +387,7 @@ sub registerSender # check if sender has been already registered $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND requestor = ? AND service = ? AND client_type = ? AND type = ? AND receive_own_events = ? AND description_tags = ? AND ip_net_client = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in registerSender: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare check statement in $function_name: $DBI::errstr\n")} $sth->execute($hostname, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my $result = $sth->fetchrow(); @@ -380,7 +397,7 @@ sub registerSender die("Error - sender has already been registered at $result"); } else { $sth = $DBH->prepare("INSERT INTO clients VALUES (?,?,?,?,?,?,?,?,?,?);"); - if (!defined $sth) {die("Cannot do statement in registerSender: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot do statement in $function_name: $DBI::errstr\n")} $sth->execute(undef, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); write2log("info", "New sender $hostname (service: $service, cidr: $ip_net_client) was registered"); return 1; @@ -402,8 +419,10 @@ sub registerReceiver my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'registerReceiver'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to registerReceiver from: $ip ($cn) - access allowed only from localhost"); + write2log ("err", "Unauthorized access to $function_name from: $ip ($cn) - access allowed only from localhost"); die("Access denied - access allowed only from localhost!"); } else { # variables defined by method @@ -421,7 +440,7 @@ sub registerReceiver # check if receiver has been already registered $sth = $DBH->prepare("SELECT registered FROM clients WHERE hostname = ? AND requestor = ? AND service = ? AND client_type = ? AND type = ? AND receive_own_events = ? AND description_tags = ? AND ip_net_client = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in registerReceiver: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare check statement in $function_name: $DBI::errstr\n")} $sth->execute($hostname, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my $result = $sth->fetchrow(); @@ -431,7 +450,7 @@ sub registerReceiver die("Error - receiver has already been registered at $result"); } else { $sth = $DBH->prepare("INSERT INTO clients VALUES (?,?,?,?,?,?,?,?,?,?);"); - if (!defined($sth)) {die("Cannot do statement in registerReceiver: $DBI::errstr\n")} + if (!defined($sth)) {die("Cannot do statement in $function_name: $DBI::errstr\n")} $sth->execute(undef, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); write2log("info", "New receiver $hostname (type: $type, cidr: $ip_net_client: receive_own_events: $receive_own_events) was registered"); return 1; @@ -453,8 +472,10 @@ sub unregisterClient my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'unregisterClient'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to unregisterClients from: $ip ($cn) - access allowed only from localhost"); + write2log ("err", "Unauthorized access to $function_name from: $ip ($cn) - access allowed only from localhost"); die("Access denied - access allowed only from localhost!"); } else { # parse SOAP data oject @@ -462,7 +483,7 @@ sub unregisterClient # check if receiver has been already registered $sth = $DBH->prepare("SELECT client_id, hostname, service, client_type FROM clients WHERE client_id = ? LIMIT 1;"); - if (!defined $sth) {die("Cannot prepare check statement in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare check statement in $function_name: $DBI::errstr\n")} $sth->execute($client_id); my ($id, $hostname, $service, $client_type) = $sth->fetchrow(); @@ -473,18 +494,18 @@ sub unregisterClient } else { if ($client_type eq 's') { $sth = $DBH->prepare("DELETE FROM clients WHERE client_id = ?;"); - if (!defined $sth) {die("Cannot do delete statement of sender in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot do delete statement of sender in $function_name: $DBI::errstr\n")} $sth->execute($client_id); $sth = $DBH->prepare("UPDATE events SET valid = 'f' where hostname = ? AND service = ?;"); - if (!defined $sth) {die("Cannot do unvalidation statement in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot do unvalidation statement in $function_name: $DBI::errstr\n")} $sth->execute($hostname, $service); write2log("info", "Sender $hostname (client_id: $client_id, service: $service) was deleted and its data were invalidated" ); return 1; } else { $sth = $DBH->prepare("DELETE FROM clients WHERE client_id = ?;"); - if (!defined $sth) {die("Cannot do delete statement of receiver in unregisterClient: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot do delete statement of receiver in $function_name: $DBI::errstr\n")} $sth->execute($client_id); write2log("info", "Receiver $hostname (client_id: $client_id) was deleted" ); @@ -507,14 +528,16 @@ sub getClients my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'getClients'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to getClients from: $ip ($cn) - access allowed only from localhost"); + write2log ("err", "Unauthorized access to $function_name from: $ip ($cn) - access allowed only from localhost"); die("Access denied - access allowed only from localhost!"); } else { my (@clients, $client); my ($client_id, $hostname, $registered, $requestor, $service, $client_type, $type, $receive_own_events, $description_tags, $ip_net_client); my $sth = $DBH->prepare("SELECT * FROM clients ORDER BY client_id ASC;"); - if (!defined $sth) { die("Cannot prepare statement in getClients: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; while ( my @result = $sth->fetchrow() ) { @@ -562,8 +585,10 @@ sub getStatus my $ip = $ENV{'REMOTE_ADDR'}; my $local_ip = $ENV{'SERVER_ADDR'}; + my $function_name = 'getStatus'; + if ($local_ip ne $ip) { - write2log ("err", "Unauthorized access to getStatus from: $ip ($cn) - access allowed only from localhost"); + write2log ("err", "Unauthorized access to $function_name from: $ip ($cn) - access allowed only from localhost"); die("Access denied - access allowed only from localhost!"); } else { my ($sth, @status); @@ -585,35 +610,35 @@ sub getStatus # sum of records in table events $sth = $DBH->prepare("SELECT count(*) FROM events WHERE valid = 't';"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $events_sum = $sth->fetchrow(); if (!defined $events_sum) { $events_sum = "none" } # id of last record in table events $sth = $DBH->prepare("SELECT max(id) FROM events;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $events_last_id = $sth->fetchrow(); if (!defined $events_last_id) { $events_last_id = "none" } # timestamp of first record in table events $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT min(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $events_first_timestamp = $sth->fetchrow(); if (!defined $events_first_timestamp) { $events_first_timestamp = "none" } # timestamp of last record in table events $sth = $DBH->prepare("SELECT received FROM events WHERE id = (SELECT max(id) FROM events);"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $events_last_timestamp = $sth->fetchrow(); if (!defined $events_last_timestamp) { $events_last_timestamp = "none" } # sum of records in table clients $sth = $DBH->prepare("SELECT count(*) FROM clients;"); - if (!defined $sth) { die("Cannot prepare statement in getStatus: $DBI::errstr\n") } + if (!defined $sth) { die("Cannot prepare statement in $function_name: $DBI::errstr\n") } $sth->execute; my $clients_sum = $sth->fetchrow(); if (!defined $clients_sum) { $clients_sum = "none" } @@ -639,7 +664,7 @@ sub getStatus # statistics of senders if ($clients_sum != 0) { $sth = $DBH->prepare("SELECT client_id, hostname, service FROM clients WHERE client_type = 's' ORDER BY client_id ASC;"); - if (!defined $sth) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} + if (!defined $sth) {die("Cannot prepare statement in $function_name: $DBI::errstr\n")} $sth->execute; my ($client_id, $hostname, $service); my $client_status; @@ -647,13 +672,13 @@ sub getStatus my $sth2; # sum of stored events $sth2 = $DBH->prepare("SELECT count(*) FROM events WHERE hostname = ? AND service = ?;"); - if (!defined $sth2) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} + if (!defined $sth2) {die("Cannot prepare statement in $function_name: $DBI::errstr\n")} $sth2->execute($hostname, $service); my $count = $sth2->fetchrow(); if (!defined $count) {$count = "none"} # timestamp of last stored event $sth2 = $DBH->prepare("SELECT max(received) FROM events WHERE hostname = ? AND service = ?;"); - if (!defined $sth2) {die("Cannot prepare statement in getStatus: $DBI::errstr\n")} + if (!defined $sth2) {die("Cannot prepare statement in $function_name: $DBI::errstr\n")} $sth2->execute($hostname, $service); my $timestamp = $sth2->fetchrow(); if (!defined $timestamp) {$timestamp = "none"} diff --git a/src/warden-server/sh/install.sh b/src/warden-server/sh/install.sh index cd84921..72fb228 100755 --- a/src/warden-server/sh/install.sh +++ b/src/warden-server/sh/install.sh @@ -227,6 +227,13 @@ make_server_conf() # Warden server in a single getNewEvents client function call #------------------------------------------------------------------------------- \$MAX_EVENT_LIMIT = \"1000000\"; + +#------------------------------------------------------------------------------- +# VALID_STRINGS - validation hash containing allowed event attributes +#------------------------------------------------------------------------------- +%VALID_STRINGS = ( +\"type\" => [\"portscan\", \"bruteforce\", \"spam\", \"phishing\", \"botnet_c_c\", \"dos\", \"malware\", \"copyright\", \"webattack\", \"test\", \"other\", \"_any_\"], +); " > $server_conf 2> $err; ret_val=`echo $?` if [ $ret_val -eq 0 ]; then @@ -281,7 +288,7 @@ create_symlinks() #------------------------------------------------------------------------------- # list of used Perl modules -modules=(SOAP::Lite SOAP::Transport::HTTP DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509) +modules=(SOAP::Lite SOAP::Transport::HTTP DBI DBD::mysql Format::Human::Bytes Sys::Syslog File::Basename Net::CIDR::Lite DateTime Getopt::Std Switch IO::Socket::SSL MIME::Base64 Crypt::X509 List::Util) # read input while getopts "d:k:c:a:Vh" options; do -- GitLab