Linux : ModSecurity log analysis with Modgrep

ModSecurity is a popular open source Web Application Firewall that can be installed with popular web servers including Apache, IIS, and NGINX. Modsecurity log analysis can be configured via sequential or concurrent audit logging. Concurrent logging offer improved performance on extremely busy servers, but it creates a LOT of files and directories, so for simplicity many admins opt for serial logging.

To configure serial audit logging you would normally add to Apache’s httpd.conf an include statement for, say, modsec2.conf, which in turn contains the config details for ModSecurity, including the directives regarding the logging type and logfile location:

On a cPanel server, running the Atomic Corp rules and following their setup guides the audit log is typically located at /usr/local/apache/logs/modsec_audit.log

The sysadmin’s problem

OK, so when a malicious request is made to the server, ModSecurity hopefully stops it, and two things happen. It gets logged into the web server’s error_log and also to ModSecurity’s audit log. The web server error log entry may look like this

Not everything gets put into the error_log, so modsecurity log analysis is often necessary. Here’s the corresponding entry from ModSecurity’s audit log file.

The problem with the sequential file is that each log entry can span dozens of lines. So, when an interception gets logged in the web server’s error_log, and you want to go look for it, grep isn’t a whole lot of use. Even using the context switches -A or -B with grep won’t really help because the entries can vary in numbers of lines. The only way to reliably see the whole entry is with the less command and then searching through for the unique_id given at the end of the error_log entry. Slow, time consuming, and difficult to get a better picture of what’s going on.

Of course, you could try a Perl one liner like this

and you could probably create a shell alias for it and pass it a search term as an argument, but it’s usefulness will be limited.

ModSecurity log analysis made easy with Modgrep

So, Perl came to the rescue – it’s my thing. Instead of parsing the file a line at a time, it made sense to change the normal Perl record separator (dollar slash) $/ (which is a newline) to the pattern normally found at the end of each log entry – which is usually of the pattern –……..-Z– followed by a newline. So Perl gobbles in whole audit log entries at a time, making it much much easier to parse and collect statistics. This is actually faster than grep.

Here is a script you can use. Don’t forget to make it executable before trying to run it.

This script will show all matching audit log entries for a given search term, and provides a handy summary at the end of all the rule ID’s and descriptions relating to the search. For example, on one production server, searching as follows

gave all of the macthing log entries, plus this summary at the end:


, ,

7 Responses to Linux : ModSecurity log analysis with Modgrep

  1. Robert Paprocki October 15, 2014 at 00:55 #

    Nice approach, certainly fills a void in the sysadmin world (minus the bareword file hand 😉 ). I made a patch for mod_sec that implements JSON logging (, negating the problem; would definitely be interested in your thoughts!

    • steve December 4, 2014 at 12:26 #

      How are you enabling full transaction logging based on nothing more than the matching of rules?

  2. sajjad May 29, 2015 at 10:37 #

    dear author

    can we generate results output like CSV file from above and have both sheets one actual attacks and summary in other sheet ?

    • steve August 26, 2015 at 06:22 #

      Hi – not with the script as it is, but you could [easily] modify it to create other report formats 😉

  3. Joe H. September 16, 2015 at 16:47 #

    I have some enhancements that I made to this, but I made the mistake of doing it on work time, and I’m now jumping through all of the hoops to try to release it. Could you make a specific statement about the license that you’ve released the code under? (as this is going to have to go through the legal department & such)

    To give you an idea of the enhancements, here’s the expanded help for it:

    ./modgrep [-h] [-acdDeiqtv] [-f file] [-S sections] [-I id] [-V ignore] [-s search]

    (no args) : same as -h
    -h : help : print this message
    -f file : log file to search (defaults to /usr/local/apache/logs/modsec_audit.log)
    -c : (experimental) assume concurrent logs (defaults to today’s directory)

    Search string options:
    -s search : string to match on – enclosed in quotes if it contains special characters
    WARNING : this is a regex. Escape meta characters or use ‘\.\.\.’
    (can be specified multiple times)
    -i : case (i)nsensitive matching
    -v : in(v)erse grep (only show those that didn’t match)
    (deprecated; use -V instead)
    -I id : specific (I)Ds (must appear as ‘[id “…”]’ in the logs)
    -V ignore : ignore matches with this pattern (can be specified multiple times)

    Other record filtering:
    -a : all : show all activity (defaults to Interceptions only)
    -t : today : only show records with today’s date.

    Reporting options :
    -q : quiet : summary only; don’t print matching records
    -S sections : only print the listed sections (eg, ‘-S B’ for request headers)
    -e : errors : also show Apache errors in summary report

    Debugging options :
    -d : debug : report & display record when parsing fails
    -D : Developer : stop after processing one record

    It is possible to specify some arguments more than once (-I, -V, -s)
    A block must match ALL patterns.
    IDs are treated separately — a chunk must match any one ID.


  1. Mod_Security JSON Audit Logs, Revisited - September 8, 2015

    […] audit logs as JSON data, rather than the module’s native format (which is… err… difficult to parse). My initial approach was incomplete, needlessly introduced additional dependencies, and […]

Leave a Reply

Time limit is exhausted. Please reload CAPTCHA.