Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/pentesting-web/proxy-waf-protections-bypass.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,43 @@ Connection: close\r\n

It was possible to bypass AWS WAF because it wouldn't understand that the next line is part of the value of the header while the NODEJS server did (this was fixed).

## Multipart / parser-differential WAF bypasses

Some emergency WAF rules for parser-driven bugs try to **parse `multipart/form-data` themselves** and then scan only the reconstructed fields. This is fragile: if the WAF and the backend do **not** implement the **same grammar**, the WAF can inspect a harmless interpretation while the backend rebuilds the real payload. Treat this as a **grammar un-equivalence** problem, not as pure signature evasion.

This is especially relevant in exploit chains such as **React2Shell**, where the malicious server-side object graph can stay unchanged while only the **HTTP transport syntax** is mutated until the WAF and the origin disagree.

### High-value parser differential checks

- **Top-level `Content-Type` parsing**: duplicate `boundary=` parameters, quoted vs unquoted values, spaces, escapes, RFC 5987 parameters, multiple `Content-Type` headers, case sensitivity, invalid/non-UTF8 bytes.
- **Multipart framing**: garbage before/after the first boundary, `\r\n` vs `\n`, large body handling, duplicate field names, malformed closing markers such as ``--boundary-- ``.
- **Per-part headers**: duplicate `Content-Type`, `Content-Disposition` quirks (`filename`, `filename*=`), per-part charsets such as `utf16le` / `ucs2`, duplicate sub-headers, `Content-Transfer-Encoding`.

### Exploitable patterns

- **Duplicate parameter precedence mismatch**: if the WAF uses the last `boundary=` but the backend uses the first one, the WAF can parse an empty body while the backend parses the attacker-controlled parts.
- **Fail-open parser errors**: if malformed headers or invalid octets make the WAF parser error and the request is still forwarded, inspection is effectively disabled.
- **Per-part charset decoding gaps**: if the backend honors `Content-Type: text/plain; charset=utf16le` (or `ucs2`) inside a multipart part while the WAF scans raw bytes, blocked markers such as `:constructor` can be hidden in the encoded body. `busboy`, for example, maps `utf16le` / `ucs2` to a UTF-16 decoder.
- **Duplicate multipart sub-headers**: duplicated `Content-Type` headers inside the same part can create a second precedence mismatch where the WAF sees `charset=utf8` but the backend honors the first `charset=utf16le`.
- **Boundary termination quirks**: if the WAF accepts `--boundary-- ` as the final marker but the backend rejects the trailing whitespace, the WAF stops scanning too early and the backend keeps parsing later parts.

### Testing workflow

1. Find or build an endpoint that shows how the **backend parser** reconstructed each multipart field.
2. Keep the **backend payload** identical and mutate only the **transport grammar**.
3. Diff the WAF decision against backend parsing while fuzzing duplicate parameters, duplicate headers, malformed octets, part charsets, and closing-boundary syntax.
4. Treat **parse error => allow** as a critical finding and validate first with safe marker strings before replaying the real exploit payload.

These ambiguities often overlap with:

{{#ref}}
http-request-smuggling/README.md
{{#endref}}

{{#ref}}
file-upload/README.md
{{#endref}}

## Generic WAF bypasses

### Request Size Limits
Expand Down Expand Up @@ -243,11 +280,13 @@ data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+ #base64 encoding the javascri
## References

- [https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/](https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/)
- [https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass](https://www.hacktron.ai/blog/react2shell-vercel-waf-bypass)
- [https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies](https://rafa.hashnode.dev/exploiting-http-parsers-inconsistencies)
- [https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/](https://blog.sicuranext.com/modsecurity-path-confusion-bugs-bypass/)
- [https://www.youtube.com/watch?v=0OMmWtU2Y_g](https://www.youtube.com/watch?v=0OMmWtU2Y_g)
- [https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization](https://0x999.net/blog/exploring-javascript-events-bypassing-wafs-via-character-normalization#bypassing-web-application-firewalls-via-character-normalization)
- [How I found a 0-Click Account takeover in a public BBP and leveraged it to access Admin-Level functionalities](https://hesar101.github.io/posts/How-I-found-a-0-Click-Account-takeover-in-a-public-BBP-and-leveraged-It-to-access-Admin-Level-functionalities/)
- [https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406](https://github.com/mscdex/busboy/blob/6b3dcf69d38c1a8d53a0b3e4c88ba296f6c91525/lib/utils.js#L403-L406)


{{#include ../banners/hacktricks-training.md}}