Read this post if you want to disable ModSecurity rules that cause 403 errors. But before you do this! First, let’s see what ModSecurity is and why we use it. Then, this post will focus on an example 403 error using WordPress since this seems to be a common issue.
Heads up!
- You will need SSH and root user access to apply the necessary fixes.
- You can no longer (in most cases) use your .htaccess file to disable ModSecurity rules.
What is ModSecurity?
ModSecurity is an open-source ‘Web Application Firewall‘ that inspects all HTTP requests and responses. ModSecurity tries to prevent malicious requests and avoid possible code leakages.
How does ModSecurity do this? ModSecurity uses regular expressions that attempt to match frequently used attacks. It will then throw a 403 error if a rule is triggered.
Why use ModSecurity?
Let’s look at the statistics to see why you need ModSecurity:
- Acunetix’s Web Application Vulnerability Report 2019 mentions that 46% of websites have high-security vulnerabilities. They also say that 87% of websites have medium-security vulnerabilities.
- Akamai’s Summer 2018 State of the Internet/Security: Web Attack report mentions that “Application-layer attacks such as SQL injection or cross-site scripting” increased 38%.
In other words, we can all do with a little help to be more secure. Hopefully, you agree that it’s a good idea to use ModSecurity to help you protect your website.
Here are some frequently used attacks that ModSecurity will help prevent:
- SQL Injection (SQLi)
- Cross-Site Scripting (XSS)
- Local File Inclusion (LFI)
- Remote File Inclusion (RFI)
- Remote Code Execution (RCE)
- PHP Code Injection
- HTTP Protocol Violations
- Session Fixation
- Scanner Detection
- Metadata/Error Leakages
- GeoIP Country Blocking
ModSecurity will also prevent accidental code leakages. For example, a web application can produce an error that reveals sensitive details about the Application or server. ModSecurity protection reduces the chance that attackers will see these details. See this list of possible PHP errors that ModSecurity will prevent from displaying in the browser.
Example of a 403 error affecting WordPress
You will see an error similar to the following “updating failed” error in WordPress:
The message provided could be because of many other reasons. The reasons include, but are not limited to: incorrect server configuration, corrupt .htaccess files, incorrect file permissions, and much more. You will, therefore, need more information to determine if this message is a 403 error.
To clarify the reason behind the “updating failed” error:
First, open the network tab of your browser’s developer tools.
For Chrome and Firefox:
- On Windows/Linux use the shortcut: F12, Ctrl + Shift + I
- On Mac use the shortcut: Cmd + Opt + I
Then, look for any network information that is marked red.
You should see a 403 Forbidden error as per the image below:
Let’s confirm if ModSecurity caused the 403 error
The audit log is stored under /var/log/apache2/modsec_audit.log for Ubuntu, or /var/log/httpd/ modsec_audit.log or /var/log/modsec_audit.log for NGINX.
The ModSecurity audit log consists of sections. Named ‘A’, ‘B’, … and finally ‘Z’. The sections will be pre-pended with a unique random id. The id will look something like this: –7bfef37c-A–. Also, not all the sections are mandatory, but sections A and Z are.
Here is an example of a ModSecurity log:
--7bfef37c-A--
[28/Jun/2019:21:15:09 +0000] XRaDXfAWjRZQAAAAE 20.224.123.110 9999 173.22.10.12 443
...
--7bfef37c-B--
POST /wp-json/wp/v2/posts/91628/autosaves?_locale=user HTTP/2.0
...
...
--7bfef37c-C--
...
...
--7bfef37c-F--
HTTP/1.1 403 Forbidden
X-Frame-Options: DENY
Content-Length: 242
Connection: close
Content-Type: text/html; charset=iso-8859-1
--7bfef37c-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /wp-json/wp/v2/posts/91628/autosaves
on this server.<br />
</p>
</body></html>
--7bfef37c-H--
Message: Warning. Matched phrase "<!--" at ARGS:content. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "303"] [id "941180"] [rev "2"] [msg "Node-Validator Blacklist Keywords"] [data "Matched Data: <!-- found within ARGS:content: <!-- wp:paragraph -->\x0a<p>aaaa</p>\x0a<!-- /wp:paragraph -->\x0a\x0a<!-- wp:paragraph -->\x0a<p>aaa</p>\x0a<!-- /wp:paragraph -->"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "8"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "OWASP_CRS/WEB_ATTACK/XSS"] [tag "WASCTC/WASC-8"] [tag "WASCTC/WASC-22"] [tag "OWASP_TOP_10/A3"] [tag "OWASP_AppSensor/IE1"] [tag "CAPEC-242"]
...
--7bfef37c-Z--
Looking at the information provided in section H:
- It says that it found an unwanted tag ( “<!– ” ) in the post sent to the WordPress server.
- It indicates the ModSecurity rule number ( 941180 ) that caused the exception.
- It mentions the version of the rule that is used. In this case, it’s OWASP_CRS/3.0.0.
Look carefully to find all the rule numbers that were reported. You will need to use these rule id numbers to disable them.
Why is there a false alarm?
ModSecurity doesn’t always get it right. But, web applications don’t either. So, ModSecurity will help prevent bad code practices. It will also help avoid code leakages from poorly written/tested code.
Using a newer version of the rulesets may reduce the number of false alarms. For example, you can see an over 90% reduction of false alarms using version 3 instead of the default installed rules. Click here for instructions by ModSecurity to update your ruleset to version 3. Upgrade your version of ModSecurity before you apply the fixes mentioned in the “how to disable ModSecurity rules that cause 403 errors” post.
The audit log is stored under /var/log/apache2/modsec_audit.log for Ubuntu, or /var/log/httpd/ modsec_audit.log or /var/log/modsec_audit.log for NGINX.
...
Producer: ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/3.1.0.
...
How do you turn off ModSecurity rules based on IP?
You can turn off ModSecurity rules based on IP.
To allowlist your public IP –
Get your public IP by using https://anto.online/tools/what-is-my-public-ip/.
Next, open the modsecurity.conf file, and add the rule below:
SecRule REMOTE_ADDR "@contains 20.224.123.110" "id:1,phase:1,nolog,allow,ctl:ruleEngine=Off"
You can find this configuration file in: /etc/modsecurity/modsecurity.conf for Apache or /etc/nginx/modsec/modsecurity.conf for NIGNX.
Remember to replace ‘20.224.123.110’ with YOUR public IP.
Finally, you restart your web server. You can use one of these
sudo /etc/init.d/apache2 restart
sudo service apache2 restart
sudo restart apache2
sudo apache2ctl restart
How do you turn off a specific ModSecurity rule?
You can turn off rules by using a rule number and the SecRuleRemoveById setting. By the way – This is where the ModSecurity rule number from earlier in this post will become useful.
For example: SecRuleRemoveById 941180
You can also combine multiple rules into one rule.
For example: SecRuleRemoveById 300013 300015 300016 300017 949110 980130
Combine SecRuleRemoveById with Apache’s locationmatch directive. This directive is more specific and will only disable the rule for pages or folders that need it. NGINX will also have a similar means to apply directives. The example below disables rule id 300013, 300015, 300016, 300017, 949110 and 980130 for any page under /wp-json/
...
<locationmatch "/wp-json/">
SecRuleRemoveById 300013 300015 300016 300017 949110 980130
</locationmatch>
<LocationMatch "/wp-admin/post.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
...
You will need to place the setting inside your website’s Apache or NGINX virtual host file.
As per the example below –
<VirtualHost *:443>
ServerAdmin [email protected]
ServerName www.my.blog
ServerAlias my.blog
SecRuleEngine On
...
...
<locationmatch "/wp-json/">
SecRuleRemoveById 300013 300015 300016 300017 949110 980130
</locationmatch>
<locationmatch "/wp-admin/">
SecRuleRemoveById 300013 300015 300016 300017 949110 980130
</locationmatch>
...
You can also be more specific and disable these rules for specific pages. By the way – The following rules are used quite often to help prevent a 403 error for WordPress:
<LocationMatch "/wp-admin/post.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
<LocationMatch "/wp-admin/admin-ajax.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
<LocationMatch "/wp-admin/page.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
<LocationMatch "/wp-admin/options.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
<LocationMatch "/wp-admin/theme-editor.php">
SecRuleRemoveById 300015 300016 300017 950907 950005 950006 960008 960011 960904
</LocationMatch>
<LocationMatch "/wp-includes/">
SecRuleRemoveById 960010 960012 950006
</LocationMatch>
This virtual hosts config file is typically stored in: /etc/apache2/sites-available/ (for Ubuntu), /etc/httpd/sites-available or /etc/nginx/sites-available for NGINX.
How do you disable ModSecurity?
You can disable ModSecurity security by setting the values of the “SecRuleEngine” configuration. Think carefully before doing this, please.
The possible values are:
- On: process rules – not recommended
- Off: do not process rules
- DetectionOnly: process rules, but do not act on possible breaches
Change the SecRuleEngine in the virtual hosts config. This virtual hosts config file is typically stored in: /etc/apache2/sites-available/ (for Ubuntu), /etc/httpd/sites-available or /etc/nginx/sites-available for NGINX.
<VirtualHost *:443>
ServerAdmin [email protected]
ServerName www.my.blog
ServerAlias my.blog
...
SecRuleEngine Off
...
...
What other ways are there to disable rules?
You can also use one of the following commands to disable rules:
SecRuleRemoveByMsg
– disable rules containing specific text.
Example usage: SecRuleRemoveByMsg “FAIL”
SecRuleRemoveByTag
– disable rules by tag name.
Example usage: SecRuleRemoveByTag “WEB_ATTACK/XSS”
Where do you apply these rules?
You can alter the ModSecurity configuration either in ModSecurity itself, or the Apache/HTTPD/NGINX configuration, or (preferred) your site’s virtual host configuration.
Why not the .htaccess file? Well, you can no longer use the .htaccess configuration to set ModSecurity rules. At least as of ModSecurity 2.7.0. You can, however, compile and install ModSecurity with a “–enable-htaccess-config” flag to, alter the default configuration.
Also, note that configuration is applied in the order that they are found. So, for example, you can enable the rule “SecRuleEngine” in your Apache or NGINX configuration, and then disable the rule “SecRuleEngine” in your site’s virtual host configuration. In this case, the virtual host configuration overrides the Apache or NGINX configuration.
How do you find the ModSecurity Configuration?
The ModSecurity configuration is mostly stored under: /etc/modsecurity/modsecurity.conf.
Use one of the following Linux commands to help you find files or config.
For example, this command will find all files in the /etc/ (and its sub-folders), where the file contains the word “SecRuleEngine”.
find /etc/ -type f -exec grep -l "SecRuleEngine" {} +
Example output:
/etc/modsecurity/modsecurity.conf.save
/etc/modsecurity/crs/crs-setup.conf
/etc/modsecurity/owasp-modsecurity-crs/CHANGES
/etc/modsecurity/owasp-modsecurity-crs/crs-setup.conf.example
/etc/modsecurity/modsecurity.conf-recommended
/etc/modsecurity/modsecurity.conf
/etc/apache2/apache2.conf
Another example is this command that will find all files on the server with the name “modsecurity.conf”.
sudo find . -name "modsecurity.conf"
Example output:
./etc/modsecurity/modsecurity.conf
Finally, the following command will help you find specific text within files. For example, we can search the Audit Log for all instances of myblog.com, and include two lines before and after the occurrence.
sudo cat /var/log/apache2/modsec_audit.log | grep -C 2 myblog.com
Example output:
--0d536b31-B--
GET /xmlrpc.php HTTP/1.1
Host: myblog.com
Connection: Keep-Alive
User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 YaBrowser/18.2.0.284 Yowser/2.5
Wrapping up
In conclusion, you now have a solid understanding of how to disable ModSecurity rules that cause 403 errors.
Can you be more specific and give examples about how to turn off specific modsecurity rules for nginx?
The LocationMatch method seems to be Apache specific.
I use Blue Hose for Word Press. I am getting Mod Security blocking me from up dating any website.
Blue Host tells me that everything is working OK at there end.
Thank you