A few weeks ago I wrote a guide on how to install Modsecurity 3 on Apache HTTP for the FreeBSD operating system. However there’s a catch with that setting and with Modsecurity in general. As good as it is as a WAF you need to at least adjust its configuration to the tool one pretends to protect. Leaving it on without adjustments is, one a Royal pain in the ass, and second poor in the sense of usability. Even a fly passing by at your desk will trigger a blockage. In this how to configure Modsecurity 3 for WordPress on FreeBSD I’m going to show you how to adjust the latest iteration of Modsecurity on a FAMP stack with a WordPress on it.
If you find the articles in Adminbyaccident.com useful to you, please consider making a donation.
Use this link to get $200 credit at DigitalOcean and support Adminbyaccident.com costs.
Get $100 credit for free at Vultr using this link and support Adminbyaccident.com costs.
Mind Vultr supports FreeBSD on their VPS offer.
Pre-requisites
First of all a FAMP stack installed on a FreeBSD box. You can use one of these few scripts (adapt settings like passwords and such):
FAMP stack with TCP socket and the Event MPM on.
FAMP stack with UNIX socket and the Event MPM on.
FAMP stack with mod_php and the pre-fork MPM on.
If you prefer to deal with this by hand and not with any script I’ve written four FAMP stack guides:
These two are using the prefork MPM:
One here at Adminbyaccident.com
The other at digitalocean.com
These other two are using the Event MPM and PHP-FPM:
One in Adminbyaccident.com
The other one at digitalocean.com
If you are in doubt between which one to choose, the one with pre-fork or the one with the Event MPM, just go for the Event one. Nowadays everyone is using that and performance is much higher than using pre-fork.
A WordPress install on top of any of those configurations of the FAMP stack. You may want to use the following script for that (also adjust the settings like the DB password and so on).
WordPress install on a FAMP stack.
A Modsecurity 3 installation on a FAMP stack box. I’ve also written a small script for this.
Modsecurity 3 install script on FreeBSD.
With all these pre-requisites fulfilled it’s time to start the guide.
Step 1. Configure Modsecurity to use the WordPress exceptions file
Modsecurity on its third iteration checks HTTP requests against a series of rules and applies a score system on them. As the request is analyzed and matches the rules it obtains a score, and at the end depending on the level it gets it gets rejected or is given a pass.
# -- [[ Anomaly Scoring Mode (default) ]] --
# In CRS3, anomaly mode is the default and recommended mode, since it gives the
# most accurate log information and offers the most flexibility in setting your
# blocking policies. It is also called "collaborative detection mode".
# In this mode, each matching rule increases an 'anomaly score'.
# At the conclusion of the inbound rules, and again at the conclusion of the
# outbound rules, the anomaly score is checked, and the blocking evaluation
# rules apply a disruptive action, by default returning an error 403.
More on this and how this works can be read in the following file. You can use the ‘less’ command to give it a go.
root@modsec:~ # less /usr/local/etc/modsecurity/coreruleset/crs-setup.conf
If you take a closer look on that file you will find Mosecurity 3 on Apache has 4 levels of rules. The higher the level, the more rules that are involed into checking the HTTP request. By default the level is set to 1.
# - A paranoia level of 1 is default. In this level, most core rules
# are enabled. PL1 is advised for beginners, installations
# covering many different sites and applications, and for setups
# with standard security requirements.
# At PL1 you should face FPs rarely. If you encounter FPs, please
# open an issue on the CRS GitHub site and don't forget to attach your
# complete Audit Log record for the request with the issue.
# - Paranoia level 2 includes many extra rules, for instance enabling
# many regexp-based SQL and XSS injection protections, and adding
# extra keywords checked for code injections. PL2 is advised
# for moderate to experienced users desiring more complete coverage
# and for installations with elevated security requirements.
# PL2 comes with some FPs which you need to handle.
# - Paranoia level 3 enables more rules and keyword lists, and tweaks
# limits on special characters used. PL3 is aimed at users experienced
# at the handling of FPs and at installations with a high security
# requirement.
# - Paranoia level 4 further restricts special characters.
# The highest level is advised for experienced users protecting
# installations with very high security requirements. Running PL4 will
# likely produce a very high number of FPs which have to be
# treated before the site can go productive.
Be aware of increasing the ‘paranoia’ levels since, for example, the default and lightest level makes the autosave on WordPress to complain about the JSON format.
Updating failed. The response is not a valid JSON response.
At level 3 you won’t be able to work unless you fine tune it, which deserves its own dedicated guide. I’d recommend to leave the tool at its default basic level for most of the use cases and work and extra whenever in need.
With these few notes explained, and as you will see the tool has a nice documented configuration file, it’s now time to configure Modsecurity 3 for WordPress on FreeBSD.
The simplest way to do this is to place this settings at the bottom of the ‘crs-setup.conf’ file.
SecAction \
"id:900130,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.crs_exclusions_wordpress=1"
However I’d recommend to look for the section called ‘Application Specific Rule Exclusions’ and enable the wordpress exception by uncommenting the same lines as above. Be careful because the tool doesn’t like to have comments on its ‘SecAction’ directives. There’s a good chance for you to find something like the following.
root@modsec:~ # apachectl -t
AH00526: Syntax error on line 542 of /usr/local/etc/apache24/httpd.conf:
Rules error. File: /usr/local/etc/modsecurity/coreruleset/crs-setup.conf. Line: 385. Column: 39. Expecting an action, got: # setvar:tx.crs_exclusions_cpanel=1,\\
root@modsec:~ #
To proper configure this you need to edit the section properly and add the exception rule you desire, in this case the one for WordPress just after the ‘t:none,\’ entry.
With this configuration entry added for WordPress it’s time to activate the ruleset exceptions for it.
Step 2. Configure the ruleset to use the WordPress exceptions file
We are now in the middle step, an important one, in our configuration of modsecurity 3 for WordPress. We need to look into the ‘rules’ directory inside the ‘coreruleset’. This is the path:
/usr/local/etc/modsecurity/coreruleset/rules
In here we’ll find a ton or rules, where we will for example be able to have a look at the exceptions made for WordPress, so false positives are not triggered. That file is named: ‘REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf’.
We are interested into the ‘REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf’ file. In here we will add a directive to activate the exclusion rules for WordPress. At the very bottom of this file we have to write the following (adjust for domain name):
SecRule REQUEST_HEADERS:Host "@streq example.com" "id:1000,phase:1,setvar:tx.crs_exclusions_wordpress=1"
If a subdomain is needed, adjust accordingly.
SecRule REQUEST_HEADERS:Host "@streq subdomain.example.com" "id:1000,phase:1,setvar:tx.crs_exclusions_wordpress=1"
With this last step it’s time to restart Apache HTTP and test our configuration.
root@modsec:/usr/local/etc/modsecurity/coreruleset/rules # apachectl restart
Performing sanity check on apache24 configuration:
Syntax OK
Stopping apache24.
Waiting for PIDS: 22745.
Performing sanity check on apache24 configuration:
Syntax OK
Starting apache24.
root@modsec:/usr/local/etc/modsecurity/coreruleset/rules #
Time now for testing.
Step 3. Test Modsecurity 3
I’m not the most qualified individual to test this tool but a simple SQL injection attack will suffice to show wether Modsecurity is working or not.
Take the following expression and adjust it to your domain. Place it in your browser and access it.
https://example.com/?id=1 or ‘X’=’X’
You should be unwelcomed with a 403 response from your server.
Now for the sake of discovery you may want to disable Modsecurity all together. Visit the very bottom of your Apache HTTP main configuration file (if you’ve used my install guide) and disable these two directives by commenting them out as follows.
#modsecurity on
#modsecurity_rules_file /usr/local/etc/apache24/modsecurity-rules.conf
After that, restart the Apache HTTP server and use this above URL with the SQLi on it. Your site will probably swallow it without complaining.
Final thoughts.
No WAF is the definitive solution for security. It is one more tool in a defense in depth strategy. But having one will help anyone to despise many bots and with enough work on false positives security can be enhanced by adding more rules and upgrading the ‘paranoia’ levels as we’ve seen in this how to configure Modsecurity 3 for WordPress on FreeBSD article.
If you find the articles in Adminbyaccident.com useful to you, please consider making a donation.
Use this link to get $200 credit at DigitalOcean and support Adminbyaccident.com costs.
Get $100 credit for free at Vultr using this link and support Adminbyaccident.com costs.
Mind Vultr supports FreeBSD on their VPS offer.