Skip to main content

ModSecurity WAF: OWASP CRS Implementation Guide

ModSecurity is an open-source Web Application Firewall (WAF) that inspects HTTP requests and responses to block OWASP Top 10 vulnerabilities including SQL Injection, XSS, and file upload attacks.


Installing ModSecurity​

ModSecurity for Nginx​

# Ubuntu 22.04+
sudo apt install libmodsecurity3 libmodsecurity-dev

# Nginx module (dynamic module)
sudo apt install libnginx-mod-security2
# Or compile from source:
# git clone --depth 1 -b v3/master https://github.com/SpiderLabs/ModSecurity
# ./build.sh && ./configure && make && sudo make install

# Verify module is activated
nginx -V 2>&1 | grep ModSecurity

ModSecurity for Apache​

# Ubuntu
sudo apt install libapache2-mod-security2
sudo a2enmod security2
sudo systemctl restart apache2

# Verify installation
apache2ctl -M | grep security2
# security2_module (shared)

Installing OWASP Core Rule Set (CRS)​

# Download CRS (latest version)
cd /etc/nginx # or /etc/modsecurity
sudo git clone --depth 1 https://github.com/coreruleset/coreruleset.git /etc/modsecurity/crs

# Copy default configuration file
sudo cp /etc/modsecurity/crs/crs-setup.conf.example \
/etc/modsecurity/crs/crs-setup.conf

sudo cp /usr/share/modsecurity-crs/modsecurity.conf-recommended \
/etc/modsecurity/modsecurity.conf

ModSecurity Nginx Configuration​

# /etc/nginx/nginx.conf β€” http block

http {
# Enable ModSecurity
modsecurity on;

# Configuration file path
modsecurity_rules_file /etc/nginx/modsecurity/main.conf;
}
# /etc/nginx/modsecurity/main.conf

# Include base ModSecurity configuration
Include /etc/modsecurity/modsecurity.conf

# Include OWASP CRS configuration
Include /etc/modsecurity/crs/crs-setup.conf

# Include CRS rule files
Include /etc/modsecurity/crs/rules/*.conf

Detection Mode vs Prevention Mode​

# /etc/modsecurity/modsecurity.conf

# Detection Only mode: detects attacks, does not block
SecRuleEngine DetectionOnly

# Prevention mode: detects and blocks attacks
SecRuleEngine On

# Disabled
SecRuleEngine Off

Recommended deployment order:

  1. Start with DetectionOnly β†’ analyze logs β†’ verify false positives
  2. Configure exclusions for false positive rules
  3. Switch to On

Handling False Positives​

When legitimate requests are blocked, exclude specific rules.

# /etc/modsecurity/custom-exclusions.conf

# Disable specific rule IDs
SecRuleRemoveById 942100 # SQL Injection detection rule (if false positive)
SecRuleRemoveById 941100 # XSS detection rule

# Exclude rules for specific URIs
SecRule REQUEST_URI "@beginsWith /api/editor/" \
"id:1001,phase:1,pass,nolog,\
ctl:ruleRemoveById=941100"

# Exclude rules for specific parameters (HTML parameters in body)
SecRuleUpdateTargetById 941100 "!ARGS:content"

# IP whitelist (internal development server)
SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8" \
"id:1000,phase:1,allow,nolog,ctl:ruleEngine=Off"

ModSecurity Log Analysis​

# Audit log location (default)
cat /var/log/modsec_audit.log

# Check blocked requests
grep "Access denied" /var/log/modsec_audit.log | head -20

# Frequency analysis of triggered rule IDs
grep "id \"" /var/log/modsec_audit.log | \
grep -o 'id "[0-9]*"' | sort | uniq -c | sort -rn | head -20

# Also check in Nginx error log
grep "ModSecurity" /var/log/nginx/error.log | tail -20

CRS Paranoia Levels​

OWASP CRS provides 4 paranoia levels.

# /etc/modsecurity/crs/crs-setup.conf

# Paranoia Level settings
# 1: Basic (few false positives, recommended starting point)
# 2: More rules (some false positives possible)
# 3: Strict (use caution in production)
# 4: Maximum (very many false positives, for special environments)
SecAction \
"id:900000,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.paranoia_level=1"

Apache ModSecurity Configuration​

# /etc/apache2/mods-available/security2.conf

<IfModule security2_module>
# Include configuration files
IncludeOptional /etc/modsecurity/*.conf

# OWASP CRS
IncludeOptional /etc/modsecurity/crs/crs-setup.conf
IncludeOptional /etc/modsecurity/crs/rules/*.conf
</IfModule>
# Disable ModSecurity for a specific virtual host
<VirtualHost *:443>
ServerName internal.example.com

# Disable ModSecurity only for this VirtualHost
SecRuleEngine Off
</VirtualHost>

ModSecurity Performance Tuning​

# /etc/modsecurity/modsecurity.conf

# Minimize audit logging (improve performance)
SecAuditEngine RelevantOnly # Log only blocked requests
SecAuditLogParts ABIJDEFHZ # Log only necessary parts

# Request body inspection size limit
SecRequestBodyLimit 13107200 # 12.5 MB
SecRequestBodyNoFilesLimit 131072 # 128 KB (body excluding files)

# Response body inspection (high performance cost, enable only when needed)
SecResponseBodyAccess Off # Disabled by default

# Rule engine parallelization
SecPcreMatchLimit 500000
SecPcreMatchLimitRecursion 500000