WAF Overview

WAF Deployment Patterns

A Web Application Firewall (WAF) filters and monitors HTTP traffic between web applications and the internet. It protects against common attacks like SQL injection, XSS, and CSRF.

Inline WAF Deployment

The WAF sits directly in the request path:

ModSecurity configuration

SecRuleEngine On

SecRequestBodyAccess On

SecResponseBodyAccess On

SQL Injection prevention

SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* \

"/((\%27)|(\'))\s*((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix" \

"id:'981173',\

phase:2,\

deny,\

status:403,\

msg:'SQL Injection Attack'"

XSS prevention

SecRule ARGS "@detectXSS" \

"id:'958056',\

phase:2,\

deny,\

status:403,\

msg:'XSS Attack Detected'"

Reverse Proxy WAF

Deploy WAF as a reverse proxy for centralized protection:

Nginx with ModSecurity

server {

listen 443 ssl;

server_name app.example.com;

ModSecurity enabled

modsecurity on;

modsecurity_rules_file /etc/nginx/modsec/main.conf;

location / {

proxy_pass http://backend:8080;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

}

Cloud WAF (AWS WAF)

AWS WAF with rate limiting and SQL injection protection

resource "aws_wafv2_web_acl" "main" {

name = "main-waf"

description = "Main WAF ACL"

scope = "REGIONAL"

default_action {

allow {}

}

rule {

name = "RateLimit"

priority = 1

action {

block {}

}

statement {

rate_based_statement {

limit = 2000

aggregate_key_type = "IP"

}

}

visibility_config {

cloudwatch_metrics_enabled = true

metric_name = "RateLimit"

sampled_requests_enabled = true

}

}

rule {

name = "SQLInjection"

priority = 2

action {

block {}

}

statement {

sql_injection_match_statement {

field_to_match {

body {}

}

text_transformation {

priority = 0

type = "URL_DECODE"

}

}

}

visibility_config {

cloudwatch_metrics_enabled = true

metric_name = "SQLInjection"

sampled_requests_enabled = true

}

}

}

API Protection

APIs require different WAF rules than web applications:

Custom WAF rule for API protection

API_WAF_RULES = {

"missing_auth_header": {

"priority": 1,

"match": lambda req: "Authorization" not in req.headers,

"action": "block",

"response": 401

},

"invalid_content_type": {

"priority": 2,

"match": lambda req: (

req.method in ["POST", "PUT", "PATCH"]

and req.headers.get("Content-Type") != "application/json"

),

"action": "block",

"response": 415

},

"path_traversal": {

"priority": 3,

"match": lambda req: "../" in req.path or "..\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" in req.path,

"action": "block",

"response": 403

}

}

WAF Logging and Monitoring

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\-- Analyze blocked requests

SELECT country, COUNT(*) as blocked_count,

ARRAY_AGG(DISTINCT rule_id) as triggered_rules

FROM waf_logs

WHERE action = 'BLOCK'

AND timestamp > NOW() - INTERVAL '24 hours'

GROUP BY country

ORDER BY blocked_count DESC;

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\-- False positive analysis

SELECT rule_id, COUNT(*) as false_positives

FROM waf_logs

WHERE action = 'BLOCK'

AND downstream_status = 200

AND timestamp > NOW() - INTERVAL '7 days'

GROUP BY rule_id

ORDER BY false_positives DESC;

Conclusion

Choose the WAF deployment pattern that fits your architecture. Inline WAF offers the strongest protection but adds latency. Cloud WAF provides scalability with minimal maintenance. Reverse proxy WAF is ideal for centralized management. Tune your WAF rules carefully to minimize false positives and monitor blocked requests regularly.