From df8eb30562ceedfe3c042b1c124b308e6b317d42 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Thu, 21 Dec 2017 16:06:13 +0100 Subject: [PATCH] Introduce priority level for snort alerts. Add the ability to skip snort alerts if their priority is lower than a config-able value. In this case guardian completely will ignore each reported alert with less priority than the configured one. Signed-off-by: Stefan Schantl --- guardian.conf.example | 5 +++ guardian.in | 10 ++++-- modules/Parser.pm | 80 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/guardian.conf.example b/guardian.conf.example index 2970257..1c86150 100644 --- a/guardian.conf.example +++ b/guardian.conf.example @@ -48,6 +48,11 @@ FirewallEngine = IPtables # Monitor_PARSER = /file/wich/should/be/monitored # # Currently supported parser modules are: HTTPD, OWNCLOUD, SNORT and SSH +# +# The snort parser allows to configure an optional priority level filter, which means, alerts +# which are lower that this priority could be skipped. Valid levels are 1-4, with 1 being the highest +# (omg, omg, omg) and 4 being the lowest (a packet has passed). +# SnortPriorityLevel = "3" ## Optional settings diff --git a/guardian.in b/guardian.in index 4be2b77..46a2325 100644 --- a/guardian.in +++ b/guardian.in @@ -87,6 +87,9 @@ $mainsettings{Logger} = $logger; # Redirect perls "die" messages to the logger before exiting. $SIG{__DIE__} = sub { $logger->Log("err", "@_"); }; +# Initialize the parser module. +my $parser = Guardian::Parser->Init(%mainsettings); + # Initialize the event handler. my $events = Guardian::Events->Init(%mainsettings); @@ -199,7 +202,7 @@ sub Worker ($) { # Obtain the parser name which should be used to parse any # messages of this file. - my $parser = $monitored_files{$file}; + my $use_parser = $monitored_files{$file}; # Signal handler to kill worker. $SIG{'KILL'} = sub { threads->exit(); }; @@ -259,7 +262,7 @@ sub Worker ($) { # Send filename and message to the parser, # which will return if any actions have to be performed. - my @actions = &Guardian::Parser::Parser("$parser", @message); + my @actions = $parser->Parser("$use_parser", @message); # Send the action to the main process and put it into # the queue. @@ -461,6 +464,9 @@ sub Reload () { # Update logger object in mainsettings hash. $mainsettings{Logger} = $logger; + # Update Parser handler. + $parser->Update(\%mainsettings); + # Update Event handler. $events->Update(\%mainsettings); diff --git a/modules/Parser.pm b/modules/Parser.pm index 1a6471a..3880228 100644 --- a/modules/Parser.pm +++ b/modules/Parser.pm @@ -15,6 +15,48 @@ my %logfile_parsers = ( "ssh" => \&message_parser_ssh, ); +# +## The "Init" (Parser) function. +# +## This function is responsible to initialize the Parser as a class based object. +## It has to be called once before any parsing of messages can be done. +# +sub Init (%) { + my ( $class, %args ) = @_; + my $self = \%args; + + # Use bless to make "$self" to an object of class "$class". + bless($self, $class); + + # Return the class object. + return $self; +} + +# +## The "Update" Parser settings function. +# +## This object based function is called to update various class settings. +# +sub Update (\%) { + my $self = shift; + + # Dereference the given hash-ref and store + # the values into a new temporary hash. + my %settings = %{ $_[0] }; + + # Update snort priority level settings or disable it. + if ((defined($self->{SnortPriorityLevel})) && (exists($settings{SnortPriorityLevel}))) { + # Change settings. + $self->{SnortPriorityLevel} = $settings{SnortPriorityLevel}; + } else { + # Remove setting. + delete $self->{SnortPriorityLevel}; + } + + # Return modified class object. + return $self; +} + # ## The main parsing function. # @@ -23,7 +65,8 @@ my %logfile_parsers = ( ## any action should be performed. # sub Parser ($$) { - my ($parser, @message) = @_; + my $self = shift; + my ($parser, @message) = @_; # If no responsible message parser could be found, just return nothing. unless (exists($logfile_parsers{$parser})) { @@ -31,7 +74,7 @@ sub Parser ($$) { } # Call responsible message parser. - my @actions = $logfile_parsers{$parser}->(@message); + my @actions = $logfile_parsers{$parser}->($self, @message); # In case an action has been returned, return it too. if (@actions) { @@ -76,6 +119,7 @@ sub IsSupportedParser ($) { ## later time. # sub message_parser_snort(@) { + my $self = shift; my @message = @_; my @actions; @@ -107,13 +151,25 @@ sub message_parser_snort(@) { if($line =~ /^\s*$/) { # Variable to store the grabbed IP-address. my $address; + my $classification; # Loop through all lines of the current alert. foreach my $line (@alert) { - # Check Priority Level and skip the alert if it is to low. - #if ($line =~ /.*\[Priority: (\d+)\].*/) { - # return unless($1 < $priority); - #} + # Determine if the alert has been classified. + if ($line =~ /.*\[Classification: .*\] \[Priority: (\d+)\].*/) { + my $priority = $1; + + # Set classification to true. + $classification = "1"; + + # Obtain configured priority level. + my $priority_level = $self->{SnortPriorityLevel}; + + # Skip alerts if the priority is to low. + if ($priority < $priority_level) { + last; + } + } # Search for a line like xxx.xxx.xxx.xxx -> xxx.xxx.xxx.xxx if ($line =~ /(\d+\.\d+\.\d+\.\d+)+ -\> (\d+\.\d+\.\d+\.\d+)+/) { @@ -127,21 +183,21 @@ sub message_parser_snort(@) { $address = $1; } - # Obtain the reported reason from the headline of the alert. - if ($line =~ /.*\] (.*) \[\*\*\]/) { + # Grab the reason from a msg field of the alert. + if ($line =~ /.*msg:\"(.*)\".*/) { # Store the extracted message. $message = $1; } - # If the reason could not be determined, try to obtain it from a msg field. - elsif ($line =~ /.*msg:\"(.*)\".*/) { + # If the reason could not be determined, try to obtain it from the headline of the alert. + elsif ($line =~ /.*\] (.*) \[\*\*\]/) { # Store the extracted message. $message = $1; } } # Check if at least the IP-address information has been extracted. - if (defined ($address)) { + if ((defined ($classification)) && (defined ($address))) { # Add the extracted values and event message for the computed # event to the actions array. push(@actions, "count $address $name $message"); @@ -170,6 +226,7 @@ sub message_parser_snort(@) { ## against the SSH service. # sub message_parser_ssh (@) { + my $self = shift; my @message = @_; my @actions; @@ -228,6 +285,7 @@ sub message_parser_ssh (@) { ## against a running HTTPD service. # sub message_parser_httpd (@) { + my $self = shift; my @message = @_; my @actions; -- 2.39.2