Configure ModSecurity 3 web application firewall with OWASP Core Rule Set for advanced threat protection

Intermediate 45 min Apr 03, 2026 40 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up ModSecurity 3 with OWASP Core Rule Set 4.0 to protect web applications from SQL injection, XSS, and other attacks. Configure integration with Nginx and Apache, implement custom rules, and optimize performance for production environments.

Prerequisites

  • Root or sudo access
  • Web server (Nginx or Apache) installed
  • Basic understanding of web server configuration
  • At least 2GB RAM for compilation

What this solves

ModSecurity 3 is an open-source web application firewall (WAF) that protects your web applications from common attacks like SQL injection, cross-site scripting (XSS), and remote file inclusion. Combined with the OWASP Core Rule Set (CRS), it provides enterprise-grade threat detection and blocking capabilities. This tutorial shows you how to install ModSecurity 3, configure it with OWASP CRS 4.0, integrate it with popular web servers, and optimize performance for production use.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest security patches and dependencies.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install build dependencies

Install the required development tools and libraries needed to compile ModSecurity 3 from source.

sudo apt install -y build-essential git cmake libpcre2-dev libxml2-dev libcurl4-openssl-dev libyajl-dev libgeoip-dev liblua5.3-dev libfuzzy-dev libpcre3-dev zlib1g-dev
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y git cmake pcre2-devel libxml2-devel libcurl-devel yajl-devel GeoIP-devel lua-devel ssdeep-devel pcre-devel zlib-devel

Download and compile ModSecurity 3

Clone the ModSecurity repository and compile the library with optimizations enabled for production use.

cd /opt
sudo git clone --depth 1 -b v3.0.12 https://github.com/owasp-modsecurity/ModSecurity.git
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure --with-pcre2 --with-yajl --with-geoip --with-lua --enable-parser-generation
sudo make -j$(nproc)
sudo make install

Configure library path

Add ModSecurity libraries to the system library path so web servers can find them at runtime.

echo '/usr/local/modsecurity/lib' | sudo tee /etc/ld.so.conf.d/modsecurity.conf
sudo ldconfig

Download OWASP Core Rule Set

Download the latest OWASP CRS 4.0 which provides comprehensive protection rules against common web attacks.

cd /opt
sudo wget https://github.com/coreruleset/coreruleset/archive/v4.0.0.tar.gz
sudo tar -xzf v4.0.0.tar.gz
sudo mv coreruleset-4.0.0 /etc/modsecurity
sudo chown -R root:root /etc/modsecurity
sudo chmod -R 755 /etc/modsecurity

Create ModSecurity configuration

Set up the main ModSecurity configuration with logging, audit settings, and security policies.

# ModSecurity Configuration
SecRuleEngine On
SecRequestBodyAccess On
SecRule REQUEST_HEADERS:Content-Type "^(?:application(?:/soap\+|/)|text/)xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "^application/json" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecRule REQBODY_ERROR "!@eq 0" "id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'Error %{reqbody_error_msg}',severity:2"
SecRule MULTIPART_STRICT_ERROR "!@eq 0" "id:'200003',phase:2,t:none,log,deny,status:400, msg:'Multipart request body failed strict validation'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" "id:'200004',phase:2,t:none,log,deny,status:44"
SecRule TX:/^MSC_/ "!@streq 0" "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On

Configure OWASP Core Rule Set

Create the CRS setup configuration with custom settings for your environment and security requirements.

# OWASP CRS 4.0 Setup Configuration
Include /etc/modsecurity/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=1"
SecAction "id:900001,phase:1,nolog,pass,t:none,setvar:tx.executing_paranoia_level=1"
SecAction "id:900010,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=5"
SecAction "id:900011,phase:1,nolog,pass,t:none,setvar:tx.outbound_anomaly_score_threshold=4"
SecAction "id:900020,phase:1,nolog,pass,t:none,setvar:tx.allowed_methods=GET HEAD POST OPTIONS"
SecAction "id:900021,phase:1,nolog,pass,t:none,setvar:tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/octet-stream| |application/csp-report| |application/xss-auditor-report| |text/plain|"
SecAction "id:900022,phase:1,nolog,pass,t:none,setvar:tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0"
SecAction "id:900023,phase:1,nolog,pass,t:none,setvar:tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/"
SecAction "id:900024,phase:1,nolog,pass,t:none,setvar:tx.restricted_headers=/proxy-connection/ /lock-token/ /content-range/ /translate/ /if/"
SecAction "id:900030,phase:1,nolog,pass,t:none,setvar:tx.crs_validate_utf8_encoding=1"
SecAction "id:900031,phase:1,nolog,pass,t:none,setvar:tx.arg_name_length=100"
SecAction "id:900032,phase:1,nolog,pass,t:none,setvar:tx.arg_length=400"
SecAction "id:900033,phase:1,nolog,pass,t:none,setvar:tx.total_arg_length=64000"
SecAction "id:900034,phase:1,nolog,pass,t:none,setvar:tx.max_num_args=255"

Create log directory

Set up the directory structure for ModSecurity logs with appropriate permissions for the web server.

sudo mkdir -p /var/log/modsecurity
sudo chown www-data:www-data /var/log/modsecurity
sudo chmod 755 /var/log/modsecurity
Never use chmod 777. It gives every user on the system full access to your files. The web server user (www-data) needs write access to create log files, while maintaining security.

Nginx integration

Compile Nginx ModSecurity connector

Download and compile the Nginx connector module that enables ModSecurity integration with Nginx.

cd /opt
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git

Recompile Nginx with ModSecurity module

Get Nginx source and recompile it with the ModSecurity module enabled for dynamic loading.

sudo apt install -y nginx-dev
nginx_version=$(nginx -v 2>&1 | grep -o '[0-9.]\+')
cd /opt
sudo wget http://nginx.org/download/nginx-${nginx_version}.tar.gz
sudo tar -xzf nginx-${nginx_version}.tar.gz
cd nginx-${nginx_version}
sudo ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
sudo make modules
sudo cp objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules/
sudo dnf install -y nginx-mod-devel
nginx_version=$(nginx -v 2>&1 | grep -o '[0-9.]\+')
cd /opt
sudo wget http://nginx.org/download/nginx-${nginx_version}.tar.gz
sudo tar -xzf nginx-${nginx_version}.tar.gz
cd nginx-${nginx_version}
sudo ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
sudo make modules
sudo cp objs/ngx_http_modsecurity_module.so /usr/lib64/nginx/modules/

Configure Nginx with ModSecurity

Update the Nginx configuration to load the ModSecurity module and enable WAF protection on your sites. This configuration builds on standard Nginx reverse proxy setups with additional security layers.

load_module modules/ngx_http_modsecurity_module.so;

user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # ModSecurity
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity.conf;
    
    # Logging
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;
    
    # Basic settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Create Nginx ModSecurity rules file

Create the main rules file that Nginx will use to load ModSecurity configuration and OWASP CRS rules.

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

Include OWASP CRS setup

Include /etc/modsecurity/crs-setup.conf

Include OWASP CRS rules

Include /etc/modsecurity/rules/*.conf

Create symbolic links for CRS rules

Set up the rules directory structure and link the OWASP CRS rule files for easy management.

sudo mkdir -p /etc/modsecurity/rules
sudo ln -sf /etc/modsecurity/rules/*.conf /etc/modsecurity/rules/
for rule in /etc/modsecurity/rules/REQUEST-9*.conf; do
    sudo ln -sf "$rule" /etc/modsecurity/rules/
done
for rule in /etc/modsecurity/rules/RESPONSE-9*.conf; do
    sudo ln -sf "$rule" /etc/modsecurity/rules/
done

Apache integration

Install Apache ModSecurity module

For Apache integration, compile the mod_security2 module from source for optimal compatibility with ModSecurity 3.

sudo apt install -y apache2-dev
cd /opt
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-apache.git
cd ModSecurity-apache
sudo ./autogen.sh
sudo ./configure --with-libmodsecurity=/usr/local/modsecurity/
sudo make
sudo make install
sudo dnf install -y httpd-devel
cd /opt
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-apache.git
cd ModSecurity-apache
sudo ./autogen.sh
sudo ./configure --with-libmodsecurity=/usr/local/modsecurity/
sudo make
sudo make install

Enable ModSecurity in Apache

Create Apache configuration to load and enable ModSecurity with OWASP CRS rules. This works alongside existing Apache virtual host configurations.

LoadModule security3_module /usr/lib/apache2/modules/mod_security3.so

    # Enable ModSecurity
    modsecurity On
    
    # Include rules
    modsecurity_rules_file /etc/modsecurity/apache-modsecurity.conf
    
    # Logging
    LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" modsec
    CustomLog /var/log/apache2/modsec_audit.log modsec

Create Apache rules configuration

Set up the Apache-specific rules file that includes all ModSecurity and OWASP CRS configurations.

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

Include OWASP CRS setup

Include /etc/modsecurity/crs-setup.conf

Include OWASP CRS rules

Include /etc/modsecurity/rules/REQUEST-901-INITIALIZATION.conf Include /etc/modsecurity/rules/REQUEST-903-IP-REPUTATION.conf Include /etc/modsecurity/rules/REQUEST-905-COMMON-EXCEPTIONS.conf Include /etc/modsecurity/rules/REQUEST-910-IP-REPUTATION.conf Include /etc/modsecurity/rules/REQUEST-911-METHOD-ENFORCEMENT.conf Include /etc/modsecurity/rules/REQUEST-912-DOS-PROTECTION.conf Include /etc/modsecurity/rules/REQUEST-913-SCANNER-DETECTION.conf Include /etc/modsecurity/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf Include /etc/modsecurity/rules/REQUEST-921-PROTOCOL-ATTACK.conf Include /etc/modsecurity/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf Include /etc/modsecurity/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf Include /etc/modsecurity/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf Include /etc/modsecurity/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf Include /etc/modsecurity/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf Include /etc/modsecurity/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf Include /etc/modsecurity/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf Include /etc/modsecurity/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf Include /etc/modsecurity/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf Include /etc/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf Include /etc/modsecurity/rules/RESPONSE-950-DATA-LEAKAGES.conf Include /etc/modsecurity/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf Include /etc/modsecurity/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf Include /etc/modsecurity/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf Include /etc/modsecurity/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf Include /etc/modsecurity/rules/RESPONSE-959-BLOCKING-EVALUATION.conf Include /etc/modsecurity/rules/RESPONSE-980-CORRELATION.conf

Enable the module

Activate ModSecurity in Apache and restart the web server to apply the configuration.

sudo a2enmod modsecurity
sudo systemctl restart apache2
sudo systemctl status apache2
sudo systemctl restart httpd
sudo systemctl status httpd

Custom rules and whitelisting

Create custom rules file

Set up a custom rules file for application-specific security rules and exceptions that don't fit the standard OWASP CRS.

# Custom ModSecurity Rules

Block common attack patterns

SecRule REQUEST_URI "@detectSQLi" \ "id:1001,\ phase:2,\ block,\ msg:'SQL Injection Attack Detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'attack-sqli',\ severity:2"

Block XSS attempts

SecRule ARGS "@detectXSS" \ "id:1002,\ phase:2,\ block,\ msg:'XSS Attack Detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'attack-xss',\ severity:2"

Rate limiting per IP

SecRule IP:RATE_LIMITED "@eq 1" \ "id:1003,\ phase:1,\ deny,\ status:429,\ msg:'Rate limit exceeded',\ expirevar:ip.rate_limited=60" SecRule REQUEST_HEADERS:User-Agent "@streq \"\"" \ "id:1004,\ phase:1,\ deny,\ msg:'Empty User-Agent blocked'"

Geographic IP blocking (example)

SecGeoLookupDB /etc/modsecurity/GeoLite2-Country.mmdb SecRule GEO:COUNTRY_CODE "@streq CN" \ "id:1005,\ phase:1,\ deny,\ msg:'Access denied from country'"

Create whitelist exceptions

Configure rule exceptions for legitimate application functionality that might trigger false positives.

# ModSecurity Whitelist Rules - Application Exceptions

Allow legitimate admin panel access

SecRule REQUEST_URI "@beginsWith /admin" \ "id:2001,\ phase:1,\ pass,\ ctl:ruleRemoveTargetById=942100;ARGS:query,\ ctl:ruleRemoveTargetById=941160;ARGS:content"

API endpoint exceptions

SecRule REQUEST_URI "@beginsWith /api/v1" \ "id:2002,\ phase:1,\ pass,\ ctl:ruleRemoveById=920230,\ msg:'API endpoint - relax protocol enforcement'"

Upload functionality exceptions

SecRule REQUEST_URI "@beginsWith /upload" \ "id:2003,\ phase:1,\ pass,\ ctl:ruleRemoveTargetById=200003;FILES,\ msg:'File upload - allow multipart'"

CMS-specific exceptions (WordPress example)

SecRule REQUEST_URI "@beginsWith /wp-admin" \ "id:2004,\ phase:1,\ pass,\ ctl:ruleRemoveTargetById=931130;ARGS:action,\ ctl:ruleRemoveTargetById=942100;ARGS:post_content"

Search functionality exceptions

SecRule ARGS:search "@unconditionalMatch" \ "id:2005,\ phase:1,\ pass,\ ctl:ruleRemoveTargetById=942100;ARGS:search,\ msg:'Search query - allow SQL-like syntax'"

Include custom rules in configuration

Update your main ModSecurity configuration to include the custom rules and whitelist exceptions.

echo "Include /etc/modsecurity/custom-rules.conf" | sudo tee -a /etc/nginx/modsecurity.conf
echo "Include /etc/modsecurity/whitelist-rules.conf" | sudo tee -a /etc/nginx/modsecurity.conf

Logging and monitoring configuration

Configure advanced logging

Set up structured logging with JSON format for better integration with log analysis tools and SIEM systems.

# Advanced ModSecurity Logging Configuration

JSON format audit log

SecAuditLogFormat JSON SecAuditLogStorageDir /var/log/modsecurity/ SecAuditLogFileMode 0644 SecAuditLogDirMode 0755

Detailed audit log parts

SecAuditLogParts ABCDEFGHIJKZ

Error log configuration

SecDebugLog /var/log/modsecurity/debug.log SecDebugLogLevel 3

Performance logging

SecRule RESPONSE_STATUS "@ge 200" \ "id:9001,\ phase:5,\ pass,\ nolog,\ setvar:tx.perf_modsecrules=%{PERF_RULES},\ setvar:tx.perf_modseccombined=%{PERF_COMBINED}"

Alert on high processing time

SecRule TX:PERF_COMBINED "@gt 1000" \ "id:9002,\ phase:5,\ pass,\ log,\ msg:'ModSecurity processing time exceeded threshold: %{tx.perf_combined}ms'"

Set up log rotation

Configure logrotate to manage ModSecurity log files and prevent disk space issues in production.

/var/log/modsecurity/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 www-data www-data
    postrotate
        /bin/systemctl reload nginx > /dev/null 2>&1 || true
    endscript
}

/var/log/modsecurity/audit.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    create 644 www-data www-data
    size 100M
    postrotate
        /bin/systemctl reload nginx > /dev/null 2>&1 || true
    endscript
}

Create monitoring script

Set up automated monitoring to track ModSecurity performance and alert on security events. This complements broader security monitoring setups.

#!/bin/bash

ModSecurity Monitoring Script

LOG_FILE="/var/log/modsecurity/audit.log" ALERT_EMAIL="admin@example.com" TEMP_DIR="/tmp/modsec-monitor"

Create temp directory

mkdir -p "$TEMP_DIR"

Get current timestamp

CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S") LAST_HOUR=$(date -d '1 hour ago' +"%Y-%m-%d %H:%M:%S")

Count attacks in last hour

if [ -f "$LOG_FILE" ]; then ATTACK_COUNT=$(grep -c "severity" "$LOG_FILE" | tail -1000 | wc -l) SQL_INJECTION=$(grep -c "attack-sqli" "$LOG_FILE" | tail -100 | wc -l) XSS_ATTACKS=$(grep -c "attack-xss" "$LOG_FILE" | tail -100 | wc -l) # Alert on high attack volume if [ "$ATTACK_COUNT" -gt 50 ]; then echo "High ModSecurity alert volume: $ATTACK_COUNT attacks detected" | \ mail -s "ModSecurity Alert - High Attack Volume" "$ALERT_EMAIL" fi # Generate daily report if [ "$(date +%H)" = "06" ]; then echo "ModSecurity Daily Report - $CURRENT_TIME Total Attacks: $ATTACK_COUNT SQL Injection: $SQL_INJECTION XSS Attempts: $XSS_ATTACKS" | \ mail -s "ModSecurity Daily Report" "$ALERT_EMAIL" fi fi

Check ModSecurity performance

PROC_TIME=$(grep -o 'PERF_COMBINED=[0-9]*' "$LOG_FILE" 2>/dev/null | \ tail -100 | \ awk -F= '{sum+=$2; count++} END {if(count>0) print sum/count; else print 0}') if (( $(echo "$PROC_TIME > 500" | bc -l) )); then echo "ModSecurity performance warning: Average processing time ${PROC_TIME}ms" | \ mail -s "ModSecurity Performance Alert" "$ALERT_EMAIL" fi
sudo chmod +x /usr/local/bin/modsec-monitor.sh

Schedule monitoring with cron

Set up regular monitoring checks to proactively detect security issues and performance problems.

echo "0     /usr/local/bin/modsec-monitor.sh" | sudo crontab -

Performance tuning and optimization

Configure performance optimizations

Optimize ModSecurity for production workloads by tuning memory usage, processing limits, and rule evaluation.

# ModSecurity Performance Configuration

Memory optimization

SecRequestBodyInMemoryLimit 65536 SecRequestBodyLimit 10485760 SecRequestBodyNoFilesLimit 65536

Processing optimization

SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess Off # Disable for better performance

Sampling for high-traffic sites (inspect 10% of requests)

SecRule REQUEST_HEADERS:Host "@unconditionalMatch" \ "id:9100,\ phase:1,\ pass,\ nolog,\ skipAfter:END_SAMPLING,\ chain" SecRule TX:SAMPLING_RND "!@eq 1" \ "setvar:tx.sampling_do_sample=0" SecMarker END_SAMPLING

Skip rules for static content

SecRule REQUEST_FILENAME "@endsWith .jpg" \ "id:9101,phase:1,pass,nolog,ctl:ruleEngine=Off" SecRule REQUEST_FILENAME "@endsWith .png" \ "id:9102,phase:1,pass,nolog,ctl:ruleEngine=Off" SecRule REQUEST_FILENAME "@endsWith .gif" \ "id:9103,phase:1,pass,nolog,ctl:ruleEngine=Off" SecRule REQUEST_FILENAME "@endsWith .css" \ "id:9104,phase:1,pass,nolog,ctl:ruleEngine=Off" SecRule REQUEST_FILENAME "@endsWith .js" \ "id:9105,phase:1,pass,nolog,ctl:ruleEngine=Off"

Optimize collection timeouts

SecCollectionTimeout 600

Reduced paranoia level for performance

SecAction "id:9110,phase:1,nolog,pass,setvar:tx.paranoia_level=1"

Faster regex engine

SecRule REQUEST_URI "@unconditionalMatch" \ "id:9111,phase:1,pass,nolog,ctl:ruleEngine=DetectionOnly"

Connection pooling optimization

SecRule REMOTE_ADDR "@unconditionalMatch" \ "id:9112,phase:1,pass,nolog,initcol:ip=%{remote_addr},expirevar:ip.counter=300"

Configure rule set optimization

Selectively enable only the OWASP CRS rules needed for your application to reduce processing overhead.

# Optimized OWASP CRS Configuration

Core rules (always include)

Include /etc/modsecurity/rules/REQUEST-901-INITIALIZATION.conf Include /etc/modsecurity/rules/REQUEST-905-COMMON-EXCEPTIONS.conf Include /etc/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf

Essential security rules

Include /etc/modsecurity/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf Include /etc/modsecurity/rules/REQUEST-921-PROTOCOL-ATTACK.conf Include /etc/modsecurity/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf Include /etc/modsecurity/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf

Optional rules - include only if needed

Include /etc/modsecurity/rules/REQUEST-913-SCANNER-DETECTION.conf

Include /etc/modsecurity/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf

Include /etc/modsecurity/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf

Include /etc/modsecurity/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf

Response analysis (disable for performance)

Include /etc/modsecurity/rules/RESPONSE-950-DATA-LEAKAGES.conf

Include /etc/modsecurity/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf

Correlation rules

Include /etc/modsecurity/rules/RESPONSE-980-CORRELATION.conf

Implement caching optimizations

Configure ModSecurity with caching strategies to improve performance on high-traffic websites.

# ModSecurity Caching Configuration

IP reputation cache

SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12" \ "id:9200,\ phase:1,\ pass,\ nolog,\ ctl:ruleEngine=Off,\ msg:'Internal IP - skip processing'"

User-Agent caching

SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /etc/modsecurity/trusted-ua.txt" \ "id:9201,\ phase:1,\ pass,\ nolog,\ setvar:tx.trusted_bot=1"

Trusted bot bypass

SecRule TX:TRUSTED_BOT "@eq 1" \ "id:9202,\ phase:1,\ pass,\ nolog,\ ctl:ruleRemoveById=913100-913120"

Session-based caching

SecRule REQUEST_COOKIES:session_id "@unconditionalMatch" \ "id:9203,\ phase:1,\ pass,\ nolog,\ initcol:session=%{request_cookies.session_id},\ setvar:session.counter=+1"

Rate limiting with session awareness

SecRule SESSION:COUNTER "@gt 100" \ "id:9204,\ phase:1,\ deny,\ status:429,\ msg:'Session rate limit exceeded',\ expirevar:session.counter=300"

Create trusted user agents list

Set up a whitelist of trusted crawlers and monitoring tools to reduce false positives and processing overhead.

Googlebot
Bingbot
YandexBot
facebookexternalhit
Twitterbot
LinkedInBot
PinterestBot
Slackbot
WhatsApp
TelegramBot
UptimeRobot
StatusCake
Pingdom
Datadog Agent
New Relic
Nagios

Verify your setup

Test ModSecurity functionality

Verify that ModSecurity is properly blocking malicious requests and logging security events.

# Test SQL injection detection
curl -X GET "http://example.com/?id=1' OR '1'='1" -H "User-Agent: TestBot"

Test XSS detection

curl -X POST "http://example.com/search" -d "query=" -H "Content-Type: application/x-www-form-urlencoded"

Check ModSecurity status in web server

sudo nginx -t sudo systemctl status nginx

Verify log file creation

sudo ls -la /var/log/modsecurity/ sudo tail -f /var/log/modsecurity/audit.log

Performance verification

Test the impact of ModSecurity on your web server performance and adjust settings as needed.

# Benchmark with and without ModSecurity
ab -n 1000 -c 10 http://example.com/

Check processing time in logs

grep -o 'PERF_COMBINED=[0-9]*' /var/log/modsecurity/audit.log | tail -20

Monitor system resources

top -p $(pgrep nginx) htop

Security rule validation

Confirm that OWASP CRS rules are loading correctly and protecting against common attack vectors.

# Check loaded rules count
grep -c "SecRule" /etc/modsecurity/rules/*.conf

Validate configuration syntax

modsec-rules-check /etc/nginx/modsecurity.conf

Test specific attack patterns

echo "Testing SQL injection blocking..." curl -v "http://example.com/login?user=admin'--&pass=any" 2>&1 | grep -E "(HTTP/|blocked)" echo "Testing directory traversal blocking..." curl -v "http://example.com/../../../etc/passwd" 2>&1 | grep -E "(HTTP/|blocked)" echo "Testing command injection blocking..." curl -v "http://example.com/cmd?exec=;cat /etc/passwd" 2>&1 | grep -E "(HTTP/|blocked)"

Common issues

Symptom Cause Fix
Nginx fails to start ModSecurity module not found sudo nginx -t to check config, verify module path in load_module directive
403 Forbidden on legitimate requests OWASP CRS false positive Check audit.log for rule ID, add whitelist exception in custom rules
High CPU usage Too many rules or high paranoia level Reduce paranoia level to 1, disable response body inspection, optimize rule set
Logs not created Permission issues with log directory sudo chown www-data:www-data /var/log/modsecurity and chmod 755
Rules not loading Incorrect file paths in configuration Verify Include paths match actual file locations, check symbolic links
Memory errors Request body limits too high Adjust SecRequestBodyLimit and SecRequestBodyInMemoryLimit settings
Never use chmod 777. If you encounter permission issues with ModSecurity logs or configuration files, use specific permissions like 644 for files and 755 for directories, combined with proper ownership using chown.

Next steps

Automated install script

Run this to automate the entire setup

#modsecurity #web application firewall #owasp core rule set #nginx modsecurity #apache modsecurity #waf configuration #web security #sql injection protection #xss protection

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer