In short: ModSecurity is a web application firewall that runs in the web server; the OWASP Core Rule Set (CRS) supplies freely available rules against common attack types. For Apache the CRS project recommends ModSecurity v2; for Nginx the v3 connector or Coraza come into question. Start in blocking mode with very high anomaly thresholds, lower them step by step and handle false positives with targeted exceptions. A PHP update is not replaced by this.
Your own WAF as an additional layer
Since PHP2Shell, many companies have been asking whether they need a web application firewall. Anyone who serves their websites through Cloudflare has had protection rules active automatically since 21 October 2026, according to Cloudflare. Anyone who does not, or does not want to route traffic through a third party, can run a WAF directly on their own server.
The best-known combination for this is ModSecurity with the OWASP Core Rule Set. Both are open source and free. The CRS is a collection of general detection rules, for example against SQL injection, cross-site scripting or the injection of files. The project itself describes its goal as general attack detection with as few false positives as possible, as one building block among several.
That also names the limit. A WAF checks requests and responses; it does not repair a vulnerability in the PHP interpreter. Why you need both is described in WAF or update: why you need both.
Which engine suits your web server
The rule set needs an engine that executes it. According to the CRS documentation there are three compatible options:
| Engine | Web server | Classification per CRS project |
|---|---|---|
| ModSecurity v2 | Apache (module) | reference implementation, recommended for Apache |
| ModSecurity v3 (libModSecurity) | mainly Nginx via connector | only the Nginx connector is really usable in production; fails 2 to 4 percent of the CRS tests |
| Coraza | Go-based proxies and integrations | passes the CRS v4 test suite completely |
Some background: ModSecurity was developed for a long time by Trustwave. In 2021 Trustwave announced it would end development in 2024. On 25 January 2024 the project passed to the OWASP Foundation. For new installations, check which version your distribution ships and how current it is.
How the Core Rule Set works
By default, the CRS does not block at the first suspicious sign. It works with anomaly points: each triggered rule adds points according to its severity, and only when the sum exceeds a threshold is the request rejected.
- Severities: critical 5 points, error 4, warning 3, notice 2.
- Threshold for requests:
tx.inbound_anomaly_score_threshold, default 5. - Threshold for responses:
tx.outbound_anomaly_score_threshold, default 4. - Paranoia levels 1 to 4 in
crs-setup.conf: level 1 is the baseline protection for every server on the internet, level 2 according to the project suits applications with real user data such as online shops, levels 3 and 4 bring noticeably more false positives.
A higher paranoia level detects more but also produces more false positives. For most company websites, level 1 is the start and level 2 a later goal.
Introducing ModSecurity with OWASP CRS without paralyzing the website
For new installations, the CRS project recommends switching on blocking mode from the start, but with very high thresholds, up to 10000, and then lowering them step by step. That way you gain experience with real traffic without locking out users. You set the thresholds in crs-setup.conf:
# crs-setup.conf: start phase with very high thresholds
SecAction \
"id:900110,\
phase:1,\
pass,\
t:none,\
nolog,\
setvar:tx.inbound_anomaly_score_threshold=10000,\
setvar:tx.outbound_anomaly_score_threshold=10000"
Including it under Apache follows the order that the CRS documentation prescribes for plugins. Paths differ by distribution:
<IfModule security2_module>
SecRuleEngine On
Include /etc/modsecurity/crs/crs-setup.conf
Include /etc/modsecurity/crs/plugins/*-config.conf
Include /etc/modsecurity/crs/plugins/*-before.conf
Include /etc/modsecurity/crs/rules/*.conf
Include /etc/modsecurity/crs/plugins/*-after.conf
</IfModule>
Then evaluate the audit log defined in SecAuditLog. How to search logs systematically is described in Analyzing web server logs after an attack. Lower the thresholds in stages, for example over several weeks, until you arrive at the default value.
Handling false positives in a targeted way
False positives are normal, especially in CMS backends with editors that store HTML. The worst reaction is to switch the WAF off. Two tools are better.
First, plugins: the CRS project maintains plugins with exception rules for common applications, such as WordPress. They are copied into the plugin folder and loaded via the include lines shown above. The project keeps the official list in its plugin directory.
Second, your own narrowly scoped exceptions. Instead of switching a rule off everywhere, remove it only for the path where it interferes:
# Custom exception, load BEFORE the CRS rules (e.g. in a *-before.conf)
SecRule REQUEST_URI "@beginsWith /admin/editor/speichern" \
"id:1000010,\
phase:1,\
pass,\
nolog,\
ctl:ruleRemoveById=941100"
Take the rule ID from the false positive's audit log. Document every exception with reason and date so that it can be reviewed later.
After every change to thresholds or exceptions, test your application's critical paths: login, order, payment, contact form and editorial work. A WAF that blocks orders is quickly switched off again.
For Apache servers it is worth tackling the WAF together with the rest of the configuration; the basics are under Configuring Apache for PHP securely. How Cloudflare rules compare is shown in Cloudflare protection rules against PHP2Shell. The interim measures on the server itself are under Immediate measures if you cannot patch yet.
Conclusion: a WAF needs care
ModSecurity with the OWASP Core Rule Set gives you a powerful web application firewall without license costs and without dependence on an external service. The price is work: choose the engine to fit the web server, begin with high thresholds, evaluate false positives, maintain exceptions and keep the rules up to date.
Anyone who cannot make that effort is often better off with a well-configured cloud WAF. Anyone who does gets a layer that catches many standard attacks and provides valuable hints in the audit logs. In no case does it replace the update: against PHP2Shell, only PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 or a confirmed backport protects, followed by a restart of all PHP processes.
How does PHP SOS help?
- Choose the engine: We review web server, distribution and available packages and recommend the suitable combination.
- Introduce: We install the CRS with high starting thresholds, include suitable plugins and set up logging.
- Tune: Over several weeks we evaluate false positives, create targeted exceptions and lower the thresholds.
- Put in context: As part of WAF and virtual patching, we connect the WAF with interim measures and the path to the regular patch.
Frequently asked questions
Does the OWASP CRS protect against PHP2Shell?
You should not assume so. The Core Rule Set detects general attack patterns and is not tailored to a specific vulnerability. Cloudflare also points out that rules based on the request data alone are not enough for PHP2Shell. The PHP update remains mandatory.
Which engine should I use for Nginx?
According to the CRS project, with ModSecurity v3 only the Nginx connector is really usable in production, and v3 fails a small part of the CRS tests. Alternatively there is Coraza, which according to the project passes the CRS v4 test suite completely. For Apache the project recommends ModSecurity v2.
Is ModSecurity still maintained?
According to the CRS documentation, Trustwave had announced it would end development in 2024. On 25 January 2024 the project was handed over to the OWASP Foundation and has been continued there since.
How do I prevent the WAF from paralyzing my shop?
Start with very high anomaly thresholds, as the CRS project recommends, and lower them step by step. Evaluate the logs as you go and create targeted exceptions for your application instead of switching rules off across the board.