From: Stefan Schantl Date: Thu, 14 Jul 2016 12:21:44 +0000 (+0200) Subject: Improve snort parser. X-Git-Tag: 2.0~4^2 X-Git-Url: http://git.ipfire.org/?p=people%2Fstevee%2Fguardian.git;a=commitdiff_plain;h=8bc363c514428c39a476f38c2e8897dfa01736e4 Improve snort parser. The snort parser now can handle multiple alerts at once. Snort uses a log buffer to write to it's alert file. As a result of this, when detecting multiple events at a very short time, multiple alerts will be written at once to the alert file. The single alerts now will be seperated and parsed individually. The attackers IP-address (currently only IPv4) and the reported reason will be obtained from the alert and stored to be returned to the main parser function. Signed-off-by: Stefan Schantl --- diff --git a/modules/Parser.pm b/modules/Parser.pm index 255e6cc..e50cef7 100644 --- a/modules/Parser.pm +++ b/modules/Parser.pm @@ -76,52 +76,89 @@ sub IsSupportedParser ($) { # sub message_parser_snort(@) { my @message = @_; + my @actions; + + # Temporary array to store single alerts. + my @alert; # The name of the parser module. my $name = "SNORT"; - # Variable to store the grabbed IP-address. - my $address; - # Default returned message in case no one could be grabbed # from the snort alert. my $message = "An active snort rule has matched and gained an alert."; - # A snort alert contains multiple lines, loop through all lines - # to parse the complete alert. + # Snort uses a log buffer and a result of this, when detecting multiple + # events at once, multiple alerts will be written at one time to the alert + # file. They have to be seperated from each, to be able to parse them + # individually. foreach my $line (@message) { - # Check Priority Level and skip the alert if it is to low. - #if ($line =~ /.*\[Priority: (\d+)\].*/) { - # return unless($1 < $priority); - #} - - # Search for a line like xxx.xxx.xxx.xxx -> xxx.xxx.xxx.xxx - if ($line =~ /(\d+\.\d+\.\d+\.\d+)+ -\> (\d+\.\d+\.\d+\.\d+)+/) { - # Store the grabbed IP-address. - $address = $1; - } - - # Search for a line like xxx.xxx.xxx.xxx:xxx -> xxx.xxx.xxx.xxx:xxx - elsif ($line =~ /(\d+\.\d+\.\d+\.\d+):\d+ -\> (\d+\.\d+\.\d+\.\d+):\d+/) { - # Store the obtained IP-address. - $address = $1; - } - - # Obtain the reported reason. - if ($line =~ /.*msg:\"(.*)\".*/) { - # Store the extracted message. - $message = $1; + # Remove any newlines. + chomp($line); + + # A single alert contains multiple lines, push all of them + # a temporary array. + push(@alert, $line); + + # Each alert ends with an empty line, if one is found, + # all lines of the current processed alert have been found + # and pushed to the temporary array. + if($line =~ /^\s*$/) { + # Variable to store the grabbed IP-address. + my $address; + + # 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); + #} + + # Search for a line like xxx.xxx.xxx.xxx -> xxx.xxx.xxx.xxx + if ($line =~ /(\d+\.\d+\.\d+\.\d+)+ -\> (\d+\.\d+\.\d+\.\d+)+/) { + # Store the grabbed IP-address. + $address = $1; + } + + # Search for a line like xxx.xxx.xxx.xxx:xxx -> xxx.xxx.xxx.xxx:xxx + elsif ($line =~ /(\d+\.\d+\.\d+\.\d+):\d+ -\> (\d+\.\d+\.\d+\.\d+):\d+/) { + # Store the obtained IP-address. + $address = $1; + } + + # Obtain the reported reason from the headline of the alert. + if ($line =~ /.*\] (.*) \[\*\*\]/) { + # Store the extracted message. + $message = $1; + } + + # If the reason could not be determined, try to obtain it from a msg field. + elsif ($line =~ /.*msg:\"(.*)\".*/) { + # Store the extracted message. + $message = $1; + } + } + + # Check if at least the IP-address information has been extracted. + if (defined ($address)) { + # Add the extracted values and event message for the computed + # event to the actions array. + push(@actions, "count $address $name $message"); + } + + # The alert has been processed, clear the temporary array for storing + # the next alert. + @alert = (); } } - # Check if at least the IP-address information are obtained from the - # provided alert. - if ($address) { - # Return the extracted values. - return "$address $name $message"; + # If any actions are required, return the array. + if (@actions) { + return (@actions); } - # If we got here, the alert could not be parsed correctly, return nothing. + # If we got here, the alert could not be parsed correctly, or did not match any filter. + # Therefore it can be skipped - return nothing. return; }