Exploit for the critical RCE vulnerability in React Server Components, with WAF bypass.
- Python
- requests library
python -m venv .venv
source .venv/bin/activate
pip install requestspython exploit.py http://localhost:3000 -c "id"python exploit.py http://localhost:3000 -dpython exploit.py http://localhost:3000 -c "id" --utf16lepython exploit.py http://localhost:3000 -c "id" --junk 128python exploit.py http://localhost:3000 -c "id" --utf16le --junk 128| Flag | Description |
|---|---|
-c, --command |
Command to execute (default: id) |
-d, --detect-only |
Check vulnerability without exploitation |
--utf16le |
Declare UTF-16LE charset, send UTF-8 |
--utf16be |
Declare UTF-16BE charset, send UTF-8 |
--utf7 |
Declare UTF-7 charset, send UTF-8 |
--utf32 |
Declare UTF-32 charset, send UTF-8 |
--ibm037 |
Declare IBM037/EBCDIC charset, send UTF-8 |
--iso2022jp |
Declare ISO-2022-JP charset, send UTF-8 |
--double-charset |
Double charset trick (charset=utf-8;charset=utf-7) |
--junk KB |
Prepend junk data to bypass WAF inspection limits (recommended: 128) |
--boundary |
Use randomized multipart boundary |
--case |
Apply random case variation to HTTP headers |
--disposition |
Use Content-Disposition format variations |
--pollution |
Add dummy form fields (HTTP Parameter Pollution) |
--all |
Enable all stable WAF bypass techniques |
--chunked |
(Experimental) Use chunked transfer encoding |
--crlf |
(Experimental) Use LF-only line endings |
Note: Charset options are mutually exclusive.
The vulnerability exists in React's Flight protocol deserialization. The exploit:
- Sends a crafted multipart POST request with
Next-Actionheader - Uses prototype pollution via
$1:__proto__:thento accessChunk.prototype.then - When React resolves the fake Promise, it calls the attacker-controlled
thenmethod - The
thenmethod uses$1:constructor:constructorto get the Function constructor - Arbitrary JavaScript executes via
child_process.execSync()
All charset techniques work by declaring one charset in Content-Type but sending the body as UTF-8. WAFs that try to decode according to the declared charset get garbage and fail pattern matching, while the server ignores charset and processes correctly.
UTF-16LE (--utf16le): Declares UTF-16LE (2 bytes per char). Credit: nav1n0x.
UTF-16BE (--utf16be): Big-endian variant of UTF-16.
UTF-7 (--utf7): Declares UTF-7, a base64-like ASCII-safe encoding. Some WAFs may skip bodies with this charset.
UTF-32 (--utf32): Declares UTF-32 (4 bytes per char). Pattern matching for __proto__ completely fails.
IBM037/EBCDIC (--ibm037): Declares IBM037, a completely different character mapping used on IBM mainframes. WAFs typically can't decode this. Based on ModSecurity CRS issue #1137.
ISO-2022-JP (--iso2022jp): Japanese charset using escape sequences. WAFs may not understand escape sequence state machines.
Double charset (--double-charset): Sends charset=utf-8;charset=utf-7. WAF may read first charset while parser uses second. Based on CRS bypass research.
Junk data padding (--junk): Prepends random data (default 128KB) to push payload past WAF inspection limits (Cloudflare: 8KB, Akamai: 16KB).
Boundary obfuscation (--boundary): Randomized multipart boundary that some WAFs may not parse correctly.
Header case variation (--case): Random case in headers (e.g., cOnTeNt-DiSpOsItIoN). HTTP headers are case-insensitive but some WAFs aren't.
Disposition variation (--disposition): Extra whitespace in Content-Disposition that strict WAF regexes may miss.
Parameter pollution (--pollution): Dummy form fields to overflow WAF parameter limits.
Chunked encoding (--chunked, experimental): Split body into chunks. Some WAFs can't reassemble.
CRLF variation (--crlf, experimental): LF-only line endings instead of CRLF.
- React: 19.0.0, 19.1.0, 19.1.1, 19.2.0
- Next.js: 15.0.0-15.0.4, 16.0.0-16.0.6
- React: 19.0.1, 19.1.2, 19.2.1+
- Next.js: 15.0.5+, 16.0.7+
A vulnerable Next.js app is included in vuln-app/:
cd vuln-app
npm install
npm run build
npm run startThen in another terminal:
python exploit.py http://localhost:3000 -c "whoami"For authorized security testing only. Do not use against systems without explicit permission.