Introduce priority level for snort alerts.
authorStefan Schantl <stefan.schantl@ipfire.org>
Thu, 21 Dec 2017 15:06:13 +0000 (16:06 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Thu, 21 Dec 2017 15:06:13 +0000 (16:06 +0100)
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 <stefan.schantl@ipfire.org>
guardian.conf.example
guardian.in
modules/Parser.pm

index 2970257..1c86150 100644 (file)
@@ -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
 
index 4be2b77..46a2325 100644 (file)
@@ -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);
 
index 1a6471a..3880228 100644 (file)
@@ -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;