How to Implement ModSecurity OWASP Core Rule Set in Nginx: An In-Depth Guide

default image

If you manage an Nginx server, adding the OWASP Core Rule Set gives you a major security boost against web attacks. In this comprehensive guide, I‘ll share everything I know from years of CRS experience to help you properly implement it.

Why OWASP CRS Rules Matter

First, some background. The OWASP Foundation maintains CRS as an official set of ModSecurity web firewall rules that anyone can use for free. These rules offer protection against the OWASP Top 10 web application vulnerabilities by blocking common exploits like cross-site scripting, SQL injection, remote file inclusion etc.

CRS is maintained by a team of security researchers and updated monthly with new protections as threats evolve. It was created to provide an easy open source alternative to expensive commercial WAFs. Major sites like PayPal use it to help fend off attacks.

With hackers constantly probing sites for weaknesses, having robust rules like CRS in place lets me sleep better at night knowing my clients have one more layer of defense. The capabilities are impressive:

  • Over 100 built-in rules covering the OWASP Top 10
  • Protection against zero-day exploits
  • Automated patching against new threats like Shellshock
  • Low false positive rate when tuned
  • Weekly rule updates for new attack patterns

Let‘s look at how to tap into all this security goodness ourselves.

OWASP CRS vs Other Rulesets

CRS isn‘t your only option – there are other ModSecurity rulesets like the CIS Apache Benchmarks with some overlap in protections:

Ruleset Pros Cons
OWASP CRS Broad protection, low FPs, regularly updated Complex setup, heavy performance impact
CIS Benchmark Lightweight, Apache-focused Not updated often, less zero-day coverage

I prefer CRS for its breadth and regular maintenance. Plus OWASP‘s focus on community resources results in great documentation and support which is invaluable when first learning.

The Rising Threat of Web Attacks

Here are some statistics that highlight why having a WAF like CRS is so important:

  • Over 8.4 billion web attacks occurred in just the first half of 2020 according to Cloudfare data.
  • SQL injection and cross-site scripting remain in the OWASP Top 10 over a decade after being identified as critical risks.
  • Small and mid-sized businesses saw a 305% increase in cyberattacks in 2021 according to SecurityWeek.
  • CRS can block threats like Log4J remote code execution which compromized thousands of systems in late 2021.

With hacking attempts steadily increasing, servers exposed on the public internet need robust defenses like CRS provides. Now let‘s look at setting it up properly.

Step-By-Step CRS Installation Walkthrough

I‘ll take you through the full steps I use to set up CRS on Nginx servers securely. Follow along on your own test system:

1. Install ModSecurity and Verify It‘s Working

I won‘t cover the full ModSecurity installation process since I have another guide dedicated to that.

But in summary, you need to compile and enable the ModSecurity connector module within Nginx:

./configure --add-module=/path/to/modsecurity 

Load the module in your nginx.conf file:

load_module /path/to/modsecurity/nginx/;

And add ModSecurity configuration to your site server { } block:

modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;

Test that ModSecurity is active by adding a rule to reject all requests:

SecRuleEngine On 
SecRule REQUEST_URI "@streq /" "id:1,phase:2,deny"

If Nginx returns 403 errors on all pages, ModSecurity is working! Now we can move on to installing CRS.

2. Download the Latest Stable CRS Release

Browse to the CRS Releases page on GitHub and copy the link to the latest zip/tar file.

For example v3.3.0 as of this writing. Download it on your server:


Alternatively, you can also git clone the repo to stay on the bleeding edge development branch.

3. Extract CRS Files

Unpack the downloaded CRS archive:

tar xzvf v3.3.0.tar.gz

This will create a new directory like owasp-modsecurity-crs-3.3.0 containing:

  • crs-setup.conf – Main configuration
  • rules/ – All the rule files

We need to copy these into the Nginx configuration structure.

4. Move Rules and Configs to Nginx Folder

Copy the entire CRS rules directory into Nginx‘s conf folder:

cp -R owasp-modsecurity-crs-3.3.0/rules /etc/nginx/conf

And copy crs-setup.conf as well:

cp owasp-modsecurity-crs-3.3.0/crs-setup.conf /etc/nginx/conf

Your Nginx conf folder now contains the CRS rules and configuration needed to activate them.

5. Merge CRS Config into Main ModSecurity Config

Open the main ModSecurity config file created during installation, often /etc/nginx/modsec/main.conf or similar.

Paste the contents of crs-setup.conf at the top of this file to pull in all the base CRS settings:

# Start CRS main config

SecAction "id:900000"...  

SecDataDir "/etc/nginx/conf"
SecTmpDir "/tmp/" 

# End CRS main config

# Other ModSecurity configs below...

This imports the CRS directives needed to activate the rules.

6. Tune CRS Options for Your Environment

With the default configuration, CRS will log violations but not block requests. To enable blocking, make these changes:

A. Turn on the detection engine:

SecRuleEngine On

B. Set the default action to block:

SecDefaultAction "phase:2,log,deny" 

C. Enable logging to analyze events:

SecAuditLog /var/log/modsec_audit.log 
SecAuditLogParts ABCFZ

With that, CRS will actively block attacks! Adjust rules and parts as you see fit.

Customizing Rules to Reduce False Positives

The out-of-box CRS settings are quite strict, which can lead to legitimate requests being blocked. Here are some tips to tune rules and minimize false positives:

  • Change rule actions – For less critical rules, set to pass instead of deny or log to monitor versus block.

  • Adjust rule severity – Increase the scoring threshold needed to trigger a block for less risky rules.

  • Exclude request patterns – Use targeted SecRuleExclude for IPs, user-agents and paths that trigger incorrect blocks.

For example, one client was having all traffic from CheckPoint firewall scanners blocked due to the heavy use of encoded periods in the URLs. Adding this resolved it:

SecRuleExclude user-agent ^CheckPoint

Take time to carefully tune CRS to suit your specific application and traffic patterns. OWASP provides great documentation on customizing CRS configurations.

CRS is a Key Part of a Comprehensive Security Strategy

While CRS gives you excellent protection, it‘s not a silver bullet. You should also:

  • Hide server version banners from responses
  • Update Nginx and OS regularly
  • Limit connections per IP
  • Require strong passwords
  • Restrict which HTTP methods are allowed
  • Set secure headers like X-Frame-Options
  • Monitor for suspicious traffic patterns

Use CRS as part of a defense-in-depth approach across your whole stack.

Closing Thoughts

I hope this guide gave you a good overview of implementing OWASP CRS rules on your Nginx servers. They provide a huge security benefit and are regularly updated by the community.

Let me know if you have any other questions! I‘m happy to help out. Stay safe out there.


Written by Alexis Kestler

A female web designer and programmer - Now is a 36-year IT professional with over 15 years of experience living in NorCal. I enjoy keeping my feet wet in the world of technology through reading, working, and researching topics that pique my interest.