Last active
November 30, 2022 16:15
-
-
Save porjo/4ce7e76191d3198f6798 to your computer and use it in GitHub Desktop.
Modgrep.pl adapted from http://endlessgeek.com/2014/02/search-modsecurity-audit-log-analysis/ to parse my logs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Credit to Ryan Barnett at Spiderlabs.com for original idea | |
# | |
# Usage: modgrep.pl -a <logfile> | |
# -s <search keyword> (optional) | |
# | |
use strict; | |
use warnings; | |
use Getopt::Std; | |
use vars qw/ %opt /; | |
my $options = 'haf:s:'; | |
my $defaultlog = '/usr/local/apache/logs/modsec_audit.log'; | |
getopts( "$options", \%opt ) or &help(); | |
&help() if ($opt{h} or !%opt); | |
my $sstr; | |
my $url; | |
my $count=0; | |
my %rules; | |
if ($opt{f}) { | |
open(LOGFILE,'<',$opt{f}) || die "cant find $opt{f} file $!\n"; | |
} else { | |
open(LOGFILE,'<',$defaultlog) || die "cant find $defaultlog file $!\n"; | |
} | |
if ($opt{s}) { | |
$sstr = $opt{s}; | |
} | |
# Slurp up to the end of the next Z Section | |
$/ = "-Z--\n"; | |
while(my $chunk = <LOGFILE>) { | |
chomp $chunk; | |
if (($chunk =~ m/ Intercepted/ || $opt{a}) && (($opt{s} && $chunk =~ m/$sstr/) || !$opt{s})) { | |
$count++; | |
if ($chunk =~ m/((GET|POST) \/.*)/) { | |
$url = $1; | |
} | |
# If you use a ruleset other than Atomic's then you can change the regex below to grab the rule's ID number and descriptive text | |
while ($chunk =~ m/\[file "[^\]]+\/(.+\.conf)"\].+\[id "([\d]+)"\].+\[msg "([^"\]]+)"\]/g) { | |
my $key = "$1_$2"; | |
$rules{$key}{count}++; | |
$rules{$key}{file} = $1; | |
$rules{$key}{id} = $2; | |
$rules{$key}{url} = $url; | |
$rules{$key}{msg} = $rules{$key}{msg} ? $rules{$key}{msg} : $3; | |
} | |
$url = ''; | |
#print "####################\nEntry found for search String ($sstr)\n####################\n"; | |
#print $chunk,"-Z--\n\n"; | |
} | |
} | |
close (LOGFILE); | |
print "\n\nTotal Matches for $sstr : $count\n"; | |
print "Hits\tRule ID\tRule Filename\tRule Message\tURL\n"; | |
foreach my $rule (keys %rules) { | |
print "$rules{$rule}{count}\t$rules{$rule}{id}\t$rules{$rule}{file}\t$rules{$rule}{msg}\t$rules{$rule}{url}\n"; | |
} | |
exit; | |
sub help() { | |
print << "EOF"; | |
$0 [-h] [-a] [-f file] [-s search] | |
default : same as -h | |
-h : this help message | |
-a : show all activity (defaults to Interceptions only) | |
-f file : file to search (defaults to /usr/local/apache/logs/modsec_audit.log) | |
-s search : string to match on - enclosed in quotes if it contains spaces | |
EOF | |
exit; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment