Configuration file
It is best to put all the configuration and security rules for ModSecurity in a separate file in the conf.d
sub-directory of the Apache root directory. This prevents you from cluttering your main Apache configuration file with ModSecurity directives.
Simply start your favorite editor, create a file called modsec.conf
in the conf.d
directory, and enter the following to get started:
<IfModule security2_module> # Turn on rule engine and set default action SecRuleEngine On SecDefaultAction "phase:2,deny,log,status:403" </IfModule>
Make sure the IfModule
directive uses the module identifier you provided in the LoadModule
line in httpd.conf
(security2_module in this case), otherwise Apache will ignore everything between the start and end of IfModule
.
SecRuleEngine On
turns on the rule engine so that it will start processing rules. For debugging purposes you can also set this to Off
(which will turn off rule processing) or DetectionOnly
, which will process rules but not take any action, even if a rule matches (which is helpful if you want to test that rules are working, but not block any requests should there be a problem with the rules).
The SecDefaultAction
line above specifies what happens when a rule match occurs. In this case we want ModSecurity to deny the request with a status code 403
("Forbidden"), and to write a log entry (which will show up in the Apache error log and the ModSecurity audit log). The default action is to allow requests even if a rule matches, so it is important to add this line to make sure any matching rule results in the request being denied.
You may be wondering what the phase:2
statement in the above directive does. ModSecurity divides the processing of a request into five phases—request headers, request body, response headers, response body and logging:
Phase number |
Phase name |
Phase occurs |
---|---|---|
1 |
|
Right after Apache has read the headers of the HTTP request. |
2 |
|
After the request body has been read. Most ModSecurity rules are written to be processed in this phase. |
3 |
|
Right before the response headers are sent back to the client. |
4 |
|
Before the response body is sent back to client. Any processing of the response body to inspect for example data leaks should take place in this phase. |
5 |
|
Right before logging takes place. At this point requests can no longer be blocked—all you can do is affect how logging is done. |
As can be seen by the table, the most useful phase when we want to inspect incoming HTTP requests is the request body phase, in which all of the request headers, as well as the body, are available. By specifying phase:2
for the default action, subsequent rules will all be processed in phase 2 unless another phase is specified in a rule.
To override the default phase for a rule, you use the phase
directive, as can be seen in this example, which stops processing and denies the request if the request header's user-agent field contains the string WebVulnScan
, which is a script to find weaknesses in web servers:
SecRule REQUEST_HEADERS:User-Agent "WebVulnScan" "phase:1"
This will cause the rule to be processed in phase 1—after the request headers have been received.
Completing the configuration
To complete the configuration we will introduce some additional directives. Here is the complete basic configuration file:
<IfModule security2_module> # Turn on rule engine and set default action SecRuleEngine On SecDefaultAction "phase:2,deny,log,status:403" # Configure request body access and limits SecRequestBodyAccess On # Debug log settings SecDebugLog logs/modsec_debug.log SecDebugLogLevel 0 </IfModule>
The SeqRequestBodyAccess On
directive turns on processing of HTTP request bodies. This allows us to inspect uploads done via POST requests. When this directive is enabled, ModSecurity will buffer the request body in memory and process it before giving Apache access to it for the remaining processing.
Using the SecDebugLog
directive, we specify the path to the debug log file. In this case it will be stored in the logs
sub-directory of the Apache root. We set the SecDebugLogLevel
to 0
, meaning no debug data will be recorded. It's useful to have this in the configuration file so that the debug log level can be changed should we need to debug the ruleset.