How to disable ModSecurity rules that cause 403 errors

WordPress

Read this post if you want to disable ModSecurity rules that cause 403 errors. But before you do this! Let’s see what ModSecurity is and why we use it. 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:

In other words, we can all do with a little help to be more secure. Hopefully, you agree that its a good idea to use ModSecurity to help you protect your website.

Here are some frequently used attacks that ModSecurity will help prevent:

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:

WordPress 5.x.x Updating Failed Error

The message provided could be because of many other reasons. The reasons include, but is 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 is 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. 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. You can see an over 90% reduction of false alarms by 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 whitelist 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 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 webmaster@my.blog
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 webmaster@my.blog
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 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. 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.

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

This command will find all files on the server with the name “modsecurity.conf”.

sudo find . -name "modsecurity.conf"

Example output:

./etc/modsecurity/modsecurity.conf

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

Conclusion

You should now have a solid understanding of how to disable ModSecurity rules that cause 403 errors.

About Anto

Hi, my name is Anto! I am a cloud computing hobbyist! Give me anything to do with the cloud, and I am interested. I work for a Cloud computing company by day and as a Cloud computing hobbyist by night! My projects use PHP, NodeJs, Ubuntu, MySQL and of course Amazon Web Services. Hopefully, my blog aids your cloud journey! Feel free to post a comment and share your thoughts.

View all posts by Anto →

Leave a Reply

Your email address will not be published. Required fields are marked *