WAF Rules for OWASP Top 10 Protection: ModSecurity, AWS WAF, and Custom Rules
A Web Application Firewall is your first line of defense against the attacks that compromise applications every day — SQL injection, cross-site scripting, and request smuggling. The OWASP Top 10 catalogs the most critical web application security risks, and a properly configured firewall blocks the majority of automated attacks targeting these vulnerabilities. Therefore, this guide covers practical configuration for ModSecurity and AWS WAF, including custom rules for threats that generic rulesets miss. Crucially, a firewall is a control at the network edge, not a substitute for secure code — it buys you time and blocks noise, but the application still has to be written defensively.
Understanding OWASP Top 10 in 2026
The OWASP Top 10 evolves as attack patterns change. Broken Access Control remains the number-one risk — it is the most common vulnerability found in real-world applications. Moreover, injection attacks (SQL, NoSQL, command injection) still cause devastating breaches despite being well-understood for decades. The reason is simple: developers make mistakes, and a single unvalidated input can compromise an entire database.
Server-Side Request Forgery (SSRF) has risen in prominence because cloud environments are particularly vulnerable — an SSRF exploit against an AWS application can reach the instance metadata endpoint and steal IAM credentials. Additionally, software supply chain attacks now feature prominently, reflecting the growing threat of compromised dependencies. It is worth being honest about scope: a firewall handles injection and known-bad-pattern categories well, but it cannot reason about your authorization logic, so Broken Access Control is mostly fixed in code, not at the edge.
# ModSecurity Core Rule Set (CRS) — industry standard WAF rules
# Install CRS on Nginx with ModSecurity
git clone https://github.com/coreruleset/coreruleset.git /etc/modsecurity/crs
cp /etc/modsecurity/crs/crs-setup.conf.example /etc/modsecurity/crs/crs-setup.conf
# Enable in modsecurity.conf
cat >> /etc/nginx/modsecurity.conf << 'WAFCONF'
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsecurity/audit.log
Include /etc/modsecurity/crs/crs-setup.conf
Include /etc/modsecurity/crs/rules/*.conf
WAFCONF
How the CRS Anomaly Scoring Model Works
A common misconception is that each CRS rule blocks on its own. In modern CRS, most rules instead contribute to an anomaly score, and a single blocking rule at the end of the phase decides the verdict once the score crosses a threshold. This design dramatically reduces false positives, because one borderline match no longer denies a request — several suspicious signals must accumulate first.
# crs-setup.conf — anomaly scoring thresholds and paranoia
SecAction "id:900110, phase:1, pass, nolog, \
setvar:tx.inbound_anomaly_score_threshold=5, \
setvar:tx.outbound_anomaly_score_threshold=4"
# Paranoia level: higher = stricter, more false positives
SecAction "id:900000, phase:1, pass, nolog, \
setvar:tx.paranoia_level=1"
Paranoia Level (PL) is the dial you tune for risk tolerance. PL1 is the sensible default for most public apps; PL2 and above add aggressive rules suited to high-value targets like banking, at the cost of more tuning work. As a result, raising the threshold or lowering the paranoia level is often a better first response to false positives than disabling individual rules.
SQL Injection and XSS Protection Rules
SQL injection rules detect common patterns like single quotes followed by SQL keywords, UNION SELECT statements, and comment sequences (–). ModSecurity’s CRS includes hundreds of SQL injection signatures covering MySQL, PostgreSQL, MSSQL, and Oracle-specific syntax. However, false positives are common — legitimate content containing words like “SELECT” or apostrophes triggers rules.
Cross-site scripting (XSS) rules block script injection patterns: <script> tags, event handlers like onerror and onload, and JavaScript protocol URLs. Specifically, CRS rule 941100 detects XSS via libinjection — a library that understands HTML context and produces fewer false positives than regex-based detection. In contrast, simple regex rules flag legitimate HTML content like blog posts discussing JavaScript.
# Custom ModSecurity rules for common attack patterns
# Block SQL injection in query parameters
SecRule ARGS "@detectSQLi" \
"id:1001,\
phase:2,\
deny,\
status:403,\
log,\
msg:'SQL Injection detected in parameter',\
tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',\
severity:'CRITICAL'"
# Block XSS in request body
SecRule REQUEST_BODY "@detectXSS" \
"id:1002,\
phase:2,\
deny,\
status:403,\
log,\
msg:'XSS attack detected in request body',\
tag:'OWASP_CRS/WEB_ATTACK/XSS',\
severity:'HIGH'"
# Block path traversal attempts
SecRule REQUEST_URI "(?:\.\./){2,}" \
"id:1003,\
phase:1,\
deny,\
status:403,\
log,\
msg:'Path traversal attempt',\
severity:'CRITICAL'"
# Rate limit login attempts (brute force protection)
SecRule REQUEST_URI "@streq /api/auth/login" \
"id:1004,\
phase:1,\
pass,\
nolog,\
setvar:'ip.login_count=+1',\
expirevar:'ip.login_count=60'"
SecRule IP:LOGIN_COUNT "@gt 10" \
"id:1005,\
phase:1,\
deny,\
status:429,\
log,\
msg:'Login brute force: %{IP.login_count} attempts in 60s'"
AWS WAF Configuration and Managed Rules
AWS WAF integrates with CloudFront, ALB, and API Gateway, providing a managed firewall without server infrastructure. AWS Managed Rules include rulesets for the OWASP Top 10, known bad inputs, SQL injection, and bot control. Furthermore, AWS updates these rules automatically as new attack patterns emerge, which removes a meaningful operational burden compared with self-hosting CRS.
Combine managed rules with custom rules for your application’s specific needs. For example, if your API accepts JSON payloads, add a rule that validates Content-Type headers and rejects requests with mismatched content types — a common technique for bypassing rules that only inspect form-encoded data. Likewise, set a sane request-body inspection size; AWS WAF historically inspected only the first portion of large bodies, so attackers may try to push payloads past that boundary.
{
"Name": "CustomAPIProtection",
"Priority": 1,
"Statement": {
"RateBasedStatement": {
"Limit": 2000,
"AggregateKeyType": "IP",
"ScopeDownStatement": {
"ByteMatchStatement": {
"FieldToMatch": { "UriPath": {} },
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/api/",
"TextTransformations": [
{ "Priority": 0, "Type": "LOWERCASE" }
]
}
}
}
},
"Action": { "Block": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "APIRateLimit"
}
}
ModSecurity Versus AWS WAF: Choosing an Approach
The two options solve the same problem with different trade-offs. ModSecurity with CRS gives you deep control, full request and response inspection, and no per-request cost, but you own the servers, the rule updates, and the tuning. AWS WAF gives you a managed, horizontally scaling service with automatic rule updates and tight cloud integration, at the cost of per-request and per-rule billing and a more limited rule language.
| Factor | ModSecurity + CRS | AWS WAF |
|---|---|---|
| Hosting | Self-managed (Nginx/Apache) | Fully managed |
| Rule flexibility | Very high (full SecLang) | Moderate (statement model) |
| Response inspection | Yes | No |
| Cost model | Infra + ops time | Per rule + per request |
| Rule updates | Manual / your pipeline | Automatic (managed groups) |
In practice, many teams run both: a managed edge firewall for broad, low-effort coverage, plus ModSecurity closer to the application for response inspection and bespoke rules. Defense-in-depth tolerates overlap; a request blocked twice is not a problem.
Tuning Rules: Reducing False Positives
A firewall that blocks legitimate traffic is worse than no firewall at all. Deploy in detection mode first (ModSecurity’s SecRuleEngine DetectionOnly) and analyze logs for 1-2 weeks before enabling blocking. Identify which rules trigger on legitimate requests and create targeted exclusions for those specific URLs and parameters.
Common false positives include: form fields containing HTML (rich text editors), API endpoints receiving base64-encoded data that resembles SQL patterns, and search queries containing technical terms. Additionally, CMS platforms like WordPress trigger many rules because admin requests contain HTML, SQL-like queries, and file paths. Create per-URL rule exclusions rather than disabling rules globally, so the protection stays intact everywhere except the one endpoint that genuinely needs the exception.
# ModSecurity: targeted rule exclusions to reduce false positives
# Allow HTML in blog post editor (specific URL only)
SecRule REQUEST_URI "@beginsWith /wp-admin/post.php" \
"id:2001,\
phase:1,\
pass,\
nolog,\
ctl:ruleRemoveTargetById=941100-941999;ARGS:post_content"
# Allow base64 in API upload endpoint
SecRule REQUEST_URI "@beginsWith /api/v1/upload" \
"id:2002,\
phase:1,\
pass,\
nolog,\
ctl:ruleRemoveById=942100-942999"
Monitoring and Incident Response
WAF logs are an intelligence goldmine. Analyze blocked requests to identify attack campaigns, compromised IPs, and the specific vulnerabilities attackers are targeting. Feed the data into your SIEM (Splunk, Elastic Security) for correlation with other security signals. As a result, you can detect sophisticated multi-stage attacks that combine edge probing with other techniques.
Set up alerts for unusual patterns: a sudden spike in blocked SQL injection attempts from a single IP range, repeated requests to admin URLs from unexpected geographies, or a high rate of 403 responses. Consequently, your security team investigates proactively instead of discovering breaches months later.
Web Application Firewall Limits: When the Edge Is Not Enough
Be clear-eyed about what a firewall cannot do. It cannot fix Broken Access Control, because it does not know which user may see which record. It struggles with business-logic abuse — a perfectly valid request sequence used to drain a loyalty-points balance looks benign byte for byte. Determined attackers also evade signatures through encoding tricks, parameter pollution, and payloads delivered past body-inspection limits.
Therefore, treat the edge control as one layer among several. Parameterized queries defeat SQL injection at the database boundary regardless of what slips past the edge; output encoding and a strict Content Security Policy neutralize XSS in the browser; server-side authorization checks handle access control. A firewall that lets you sleep at night does so because it sits in front of an application that was already written to survive without it.
Related Reading:
- API Security with OAuth and Zero Trust
- Container Security: Hardening Docker Images
- Supply Chain Security for CI/CD Pipelines
Resources:
In conclusion, a well-configured Web Application Firewall blocks the majority of automated OWASP Top 10 attacks before they reach your application code. Start with ModSecurity CRS or AWS Managed Rules in detection mode, tune for false positives over 1-2 weeks, then enable blocking. Add custom rules for your application’s specific attack surface, and monitor logs for intelligence on emerging threats. The firewall is one layer in defense-in-depth — combine it with input validation, parameterized queries, and a Content Security Policy for comprehensive protection.