Web application firewall with ModSecurity

Hardening runbook. Installs ModSecurity, a web application firewall engine, in front of Apache or Nginx, then runs it with the OWASP Core Rule Set to filter malicious request content (injection, traversal, common attack patterns) before it reaches the application.

When to run

On a public-facing web application that cannot be quickly patched against common attack classes, or as a defence-in-depth layer during setup. After a log review shows injection or traversal attempts in the access log.

Approach

Run in detection-only mode first, then switch to blocking once the rules are confirmed not to break legitimate traffic. Starting in blocking mode on a live site risks rejecting real requests that happen to match a rule. The Core Rule Set, not hand-written rules, is the maintained source of detection logic.

Nginx

Install the engine and connector:

sudo apt-get install libmodsecurity3 libnginx-mod-security2

If the connector does not load automatically, add to the top of /etc/nginx/nginx.conf:

load_module modules/ngx_http_modsecurity_module.so;

Set up the configuration, starting in detection-only:

sudo mkdir -p /etc/nginx/modsec
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
echo "Include /etc/nginx/modsec/modsecurity.conf" | sudo tee /etc/nginx/modsec/main.conf

Enable it in the server block:

server {
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;
    location / { ... }
}

Apache

sudo apt-get install libapache2-mod-security2
apachectl -M | grep security        # confirm the module loaded
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Detection first, then blocking

The recommended config starts with SecRuleEngine DetectionOnly: it logs what it would block without blocking. Run in this mode long enough to confirm legitimate traffic is not matching rules, checking the audit log (/var/log/apache2/modsec_audit.log on Apache; the Nginx error log on Nginx). Once clean, switch to blocking:

sudo sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf

Risk

A switch to SecRuleEngine On before reviewing detection-mode logs can block legitimate users whose requests happen to match a rule. The detection period is the safeguard; do not skip it on a live site.

Rules

Use the OWASP Core Rule Set rather than hand-written rules for common attack classes; it is comprehensive and maintained. Hand-written SecRule directives are for application-specific cases the CRS does not cover. Note that the old SecFilter / SecFilterSelective directives were removed; current rules use SecRule.

Verify

Reload, then confirm the engine is active and a known-bad request is handled:

sudo nginx -t && sudo systemctl reload nginx          # or apachectl configtest && reload apache2
curl -s "https://example.com/?test=../../etc/passwd"  # a traversal pattern

In blocking mode this returns a 403; in detection mode it succeeds but logs a rule match. Confirm normal pages still load for legitimate requests.

Done

ModSecurity loaded with the Core Rule Set. Detection-mode logs reviewed and clean. Engine switched to On. A test attack pattern is blocked; legitimate traffic is not.

Rollback

Set SecRuleEngine DetectionOnly (stops blocking, keeps logging) or Off, and reload. For Apache, sudo a2dismod security2 && sudo systemctl reload apache2 removes it entirely. Detection-only is the safer fallback when false positives appear: it keeps visibility while stopping the blocking.

Follow-up

  • A WAF filters request content; ModEvasive handles request rate. They cover different attacks.

  • Review the audit log periodically; rule matches indicate what is being attempted against the site.