Secure your Apache2 with mod-security

3 minute read

This article will show how-to install, configure and set up apache’s mod-security module on a debian based system. This was done on Ubuntu Dapper and should fit any Debian based system.

Mod_security is an Apache 1.x/2.x module whose purpose is to tighten the Web application security by shielding the applications from attack. The idea is to filter request and web content before passing it to apache core.

Once installed, mod-security needs to be defined some rules matching patterns, filter request and HTTP stream and in the end do different actions like allowing, denying, log…

Effectively, it is an intrusion detection and/or prevention system for apache web server.

1. Installation

In order to install mod-security with apache2, you need libapache2-mod-security:

sudo apt-get install libapache2-mod-security

and then enable mod-security and reload apache2

sudo a2enmod mod-security
sudo /etc/init.d/apache2 force-reload

Once this is done, you will be able to filter GET, POST urls …. and apply different rules depending on what the page/variables/url contain.

2. Configuration

A good habit is to keep functionalities configuration files as separate from the main configuration as possible. This avoid big messed up config files.

Apache running on debian offers such a place. In /etc/apache2/apache2.conf, you can find that directive:

# Include generic snippets of statements
Include /etc/apache2/conf.d/[^.#]*

So this is the place we are going to put our mod-security statements. Create and edit /etc/apache2/conf.d/mod_security and add the following:

  <IfModule mod_security.c>
    # mod_security configuration directives
    # ...
    # Turn the filtering engine On or Off
    SecFilterEngine On
    # Some sane defaults
    #Check if URL characters where encoded
    SecFilterCheckURLEncoding On
    #Check UTF-8 encoding
    SecFilterCheckUnicodeEncoding Off
    #Allow 1 byte characters
    # Accept almost all byte values
    SecFilterForceByteRange 0 255
    # Server masking is optional
    # SecServerSignature "Microsoft-IIS/0.0"
    SecAuditEngine RelevantOnly
    # The name of the audit log file
    SecAuditLog /var/log/apache2/audit_log
    # You normally won't need debug logging
    # Debug level set to a minimum
    SecFilterDebugLog /var/log/apache2/modsec_debug_log
    SecFilterDebugLevel 0
    # Should mod_security inspect POST payloads
    SecFilterScanPOST On
    # By default log and deny suspicious requests
    # with HTTP status 500
    SecFilterDefaultAction "deny,log,status:500"

This is a default template we are going to use, what we ‘ve done here is set the engine to On (SecFilterEngine On), we check that only good url encoding and characters are passed to the HTTP request, define log files, tell mod-security to scan POST request content and finally define the default filter action which will in this case log the error to /var/log/apache2/audit_log and send a 500 error to the client.

Here is a more detailled view of what those directives are used for:

  • SecFiterEngine (On|Off): enables/disables mod-security engine
  • SecFilterCheckUrlEncoding (On|Off): check if special characters where encoded before being passed in url
  • SecFilterCheckUnicodeEncoding (On|Off): check if unicode encoding is valid. Has to be Off except if you system handles Unicode.
  • SecFilterForceByteRange: Forces requests to only contain bytes from the defined range. This can prevent stack overflow attacks. Default values 0 255 allow all bytes values.
  • SecServerSignature: Change the server signature in response headers. Note: in order to get it to work, you need apache setted with ServerTokens Full.
  • SecAuditEngine (On|Off|RelevantOnly): enable/disable mod-security logging. RelevantOnly stands for “log only request that matched a filter rule”.
  • SecAuditLog /path/to/audit_log: define the file where mod-security will write its logs.
  • SecFilterDebugLog /path/to/debug_log: define where mod-security debug log will be stored.
  • SecFilterDebugLevel (0-9): mod-security has got 10 debug level. From 0 (no debug info logged) to 9 (everything logged). Most people won’t use this (otherwise, you won’t be reading this how-to :smile:), so turn it to 0.
  • SecFilterScanPost (On|Off): by default, mod-security only scans GET datas, turning this on, you will also be able to scan POST datas (such as forms)
  • SecFilterDefaultAction ACTION: here we define the default action mod-security should take when a filter rule is matched. Here, log request and reply with a 500 Internal Server Error.

Well, now that this is setted up, it is about time to add some filters.