Repository navigation
ModSecurity
ModSecurity is a Web Application Firewall that inspects incoming HTTP requests for malicious payloads using the OWASP Core Rule Set (CRS v4).
┌──────────┐ ┌──────────────────────────────────────────────┐
│ Client │──────▶│ Nginx │
└──────────┘ │ ┌──────────────────────────────────────┐ │
│ │ ModSecurity Module │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ CRS v4 │ │ Custom Rules │ │ │
│ │ │ (OWASP) │ │ (Exclusions) │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ Decision: ALLOW / BLOCK (403) │ │ │
│ │ └────────────────────────────────┘ │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
ModSecurity is wired to the Proxy Host's Block Exploits option:
- Edit a Proxy Host
- In Details, find Options
- Enable Block Exploits
- Save
The generated Nginx configuration enables modsecurity on when Block Exploits is set (and also in demo mode). It chooses modsecurity-crs.conf for a host with caching enabled and modsecurity.conf otherwise. The included rule files come from the Nginx base image; check the active file before assuming that every CRS rule is loaded.
Tip
Start by enabling ModSecurity on your most sensitive services first (login pages, admin panels, APIs). Monitor logs before enabling it globally to avoid false positives.
The Paranoia Level (PL) controls how aggressively OWASP CRS rules inspect traffic. ShieldPM does not expose a separate PL selector in the Proxy Host editor; changes to CRS settings require editing the mounted ModSecurity configuration and checking the active rule include.
| Level | False Positives | Security | Best For |
|---|---|---|---|
| PL1 | Low | Good | Most applications |
| PL2 | Medium | High | E-commerce, sensitive APIs |
| PL3 | High | Very High | Banking, healthcare |
| PL4 | Very High | Maximum | Security-critical systems |
Warning
PL2 and above will likely block legitimate traffic from complex applications like Nextcloud, WordPress, or Grafana. Always test thoroughly and prepare exclusion rules before increasing the paranoia level.
If a legitimate request is blocked (HTTP 403 Forbidden):
Check the Nginx error log for the ModSecurity: Access denied message:
# Docker
docker logs shieldpm 2>&1 | grep "ModSecurity"
# Native / LXC
grep "ModSecurity" /data/logs/error.logLook for the rule ID in the log entry: id "920350".
Prefer the persistent exclusion files provisioned under /data/modsecurity/ (REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf for rules before CRS, or RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf for response exclusions), and verify your Nginx base image's rule includes. A host-specific advanced Nginx directive is possible only in a context where modsecurity_rules is valid:
# Exclude a single rule
modsecurity_rules '
SecRuleRemoveById 920350
';# Exclude multiple rules
modsecurity_rules '
SecRuleRemoveById 920350
SecRuleRemoveById 941100
SecRuleRemoveById 942100
';Reload the page and check that the request now passes through.
CRS includes plugins for common applications that reduce false positives:
| Plugin | Purpose |
|---|---|
| WordPress | Excludes WP admin AJAX and editor requests |
| Nextcloud | Excludes WebDAV and file upload patterns |
| phpMyAdmin | Excludes SQL-heavy admin requests |
| Drupal | Excludes Drupal-specific form patterns |
- Check the plugin files copied to
/data/modsecurity/crs-plugins/at startup, and add or configure the plugin following its own installation instructions. - Confirm that the active CRS include loads that plugin, then validate and reload Nginx. Merely placing a file in that directory does not guarantee it is executed.
Note
Plugin files must follow CRS naming conventions. See the OWASP CRS Plugins repository for available plugins.
| File | Path | Description |
|---|---|---|
| CRS Rules | /usr/local/nginx/conf/conf.d/include/coreruleset/ |
OWASP Core Rule Set |
| Custom Rules | /data/modsecurity/ |
Custom rules and exclusions |
| Plugins | /data/modsecurity/crs-plugins/ |
CRS application-specific plugins |
The startup script also seeds /data/modsecurity/modsecurity-default.conf, crs-setup.conf, and the REQUEST-900 / RESPONSE-999 exclusion files from examples when missing. These are persistent files; inspect the include paths in your Nginx image before editing them.