Open Source

SolutionBase: Set up ModSecurity on Apache for Web intrusion detection

One way to bolster the security of Apache Web servers--one of the most visible and popular targets of hackers--is to employ ModSecurity to monitor and filter Web requests from users. Learn how to install and configure this valuable Apache module.


In the constant battle against malicious Web server activity you have an ally in the form of ModSecurity, an open source Apache module designed to provide intrusion detection and prevention of HTTP exploits. The module does this by filtering requests before they are handed off to the Web server or even another module. ModSecurity can handle POST requests as well as the standard GET requests, provide detailed audit logs, and investigate post-decrypted HTTPS requests. The module engine natively understands HTTP, allowing very detailed filtering to be done. Let's take a look at how to get ModSecurity installed and go over some basic and advanced techniques for securing your Apache Web servers.

Installing ModSecurity
The latest stable version of ModSecurity (1.7.4 as of this writing) can be obtained here, along with the source code and other distribution formats such as RPMs and Debian packages. When installing from source you have a couple options. First, you can install the module as a dynamic shared object (DSO). This is the easiest method for getting ModSecurity up and running. To do this you will need to unpack the source code and execute the following commands:
/usr/local/apache/bin/apxs -cia mod_security.c
/usr/local/apache/bin/apachectl stop
/usr/local/apache/bin/apachectl start

Depending on your system the specific location of Apache may vary. The apxs program is the "APache eXtenSion" tool, and it allows for the insertion of modules into Apache.

The alternative to a dynamically loaded module is to compile it directly into Apache. This will speed up the execution time, but requires a bit more installation time. You will need to copy mod_security.c to Apache’s /src/modules/extra directory and recompile Apache with the following directives:
—activate-module=src/modules/extra/mod_security
—enable-module=security

For more information on the compilation of Apache, you might want to brush up on its documentation. You can always install dynamically to test the module out for yourself and switch to a compiled installation at a later time.

Configuring ModSecurity
In order to activate the ModSecurity module, you will also need to add some directives to the httpd.conf file. Here are some examples to get you started:
<IfModule mod_security.c>
 SecFilterEngine On
 SecFilterCheckURLEncoding On
 SecAuditEngine On
 SecAuditLog /var/log/audit.log
 SecFilterScanPOST On
 SecFilterDefaultAction "deny,log,status:500"
 SecFilter "\.\./"
 SecFilter /bin/bash
 SecServerSignature "Microsoft-IIS/2.0"
</IfModule>

Let’s look at the options one by one:
  • SecFilterEngine: This turns the ModSecurity engine On or Off. When it is on, every inbound request to the HTTP server will be analyzed.
  • SecFilterCheckURLEncoding: This allows ModSecurity to verify the encoding of URL requests, ensuring an attacker will not be able to send invalid characters to the HTTP server.
  • SecAuditEngine: This directive enables ModSecurity’s logging function. Your options here are On, Off, or RelevantOnly. When set to On, every HTTP request will be logged. When Off, nothing at all is logged. The RelevantOnly option will log only requests that matched a filter.
  • SecAuditLog: This option is used in conjunction with SecAuditEngine and specifies the location of the log file. The ModSecurity logs will provide more detailed information than a standard Apache log. Full requests and their response headers are stored.
  • SecFilterScanPOST: Another On or Off option, this allows for the scanning of POST requests. Typically only GET requests are checked.
  • SecFilterDefaultAction: As you may have deduced, this directive tells ModSecurity what the default action will be when a filter is matched. In the above example, we tell the module to deny the request, log it, and provide an HTTP 500 error message. In addition to this default action, specific actions can be set on a per-filter basis.
  • SecFilter "\.\./" : This is an example of how to disallow directory traversal. This is a common form of exploit. On a Linux system “../” changes to the next directory up and can be used to access system files or binaries that could be used maliciously.
  • SecFilter /bin/bash: This is another simple filter that will deny requests containing the string “/bin/bash”. This is a quick way to deny inbound requests targeted at common exploits using local executables.
  • SecServerSignature: An interesting feature, the SecServerSignature directive allows you to specify whatever you want as your server identification. This can limit an attacker’s ability to use standard attacks for your particular server or even OS. If you don’t want to be quite that tricky, you can have ModSecurity simply output the product type without any version information. This would be accomplished with the "ServerTokens ProductOnly" directive. Then, instead of seeing the standard "Server: Apache/1.3.19," someone scoping out your Web server would see only "Server: Apache."

Advanced filtering
In order to drill down into more specific aspects of an HTTP request, ModSecurity provides many advanced options. One of these is the SecFilterSelective directive. This allows you to filter on specific CGI variables, such as REMOTE_ADDR, REMOTE_HOST, SCRIPT_FILENAME, SERVER_PORT, and TIME_HOUR. These are just a few; see the ModSecurity documentation for a more complete list. ModSecurity also supports the full use of standard regular expressions, greatly increasing what you would like to filter. Instead of just simple strings, you can filter on ranges, digits, wildcards, or virtually any combination. The use of arguments is also supported. Any argument carried in an HTTP request can be looked at and checked. For instance, an attempt to access a Web page requiring a login may carry a field called "username" in the request. By using ARG_username in a directive you can filter or log use of specific login IDs.

And, as mentioned earlier, not only can a default action be specified, but individual filters can have distinct actions. Here are the built-in actions and what they mean.
  • Pass: Allows request to continue, further filters could still halt request.
  • Allow: Allows matching requests through, will not be tested against other filters.
  • Deny: Stops the request outright, returns a HTTP 500 error code by default.
  • Status: Used to specify an alternate HTTP error code.
  • Redirect: Matching requests are redirected to the provided URL.
  • Exec: Allows execution of a local system binary or script.
  • Log: Logs request only.
  • Nolog: Does not log request.
  • Chain: Allows you to create list of filters for more granulated security. All filters must be cleared before action is taken with the final filter.

Now let's take a look at a couple examples using some of the more advanced options.
SecFilterSelective ARG_pin "!^(|[0-9]{1,4})$"

This example looks for the argument pin carried in an HTTP request and rejects attempts to send nonnumeric entries between 1 and 4 digits in length. While your Web site code may return information on incorrect pins, this example could help if an attacker was attempting to overflow program execution by sending invalid or overlong entries.
SecFilterSelective REMOTE_ADDR "^192.168.42.$" log,chain
SecFilterSelective REQUEST_URI "index\.html" \ redirect:http://www.test.net/index2.html

In the above example, we create a chain of two filters. The first one checks incoming Web requests to see if they are sourced from the 192.168.42.x subnet. If a request matches, it is passed to the next filter down. This next filter checks to see what file is requested. If the file turns out to be index.html, the user is redirected to an alternate Web page (index2.html). Also notice the use of the \ to both precede the period before html and also to continue the directive on the next line.

There are a wide variety of options available to create advanced filtering. Every environment has different requirements, but the flexibility in ModSecurity should allow you to do just about any type of Web request filtering that you can imagine. You can start out small with basic filtering and work your way up to more advanced options.

End sum
ModSecurity is an excellent addition to any plans for securing Apache Web servers. While not intended to take the place of a firewall or intrusion detection system, it does have specific applications for securing HTTP. With its ability to filter on any HTTP or HTTPS GET or POST, you gain advanced control over every request hitting your server. It is smart enough to normalize inbound parameters before filtering against them, helping thwart an attacker’s tendency to try to evade detection. ModSecurity is surprisingly robust and definitely worth considering for every organization that relies on Apache for running public Web servers.

Editor's Picks