MongoDB 副本集 use-after-free 未认证崩溃(CVE-2026-118383)
未认证请求可让 4.4.32、5.0.35、6.0.30、7.0.48、8.0.37、8.3.16 和 9.0.7 之前的 MongoDB 副本集落后主节点崩溃。
TL;DR
- MongoDB 复制追赶阶段的一个 use-after-free 允许未认证客户端植入 waiter,使成员在成为主节点时崩溃。MongoDB 于 2026 年 11 月 10 日发布 CVE-2026-118383。
- 受影响分支上的所有副本集成员都暴露,包括分片和配置服务器成员。独立的
mongod不执行追赶,不受影响。 - MongoDB 将其评为 CVSS v4.0 9.5 Critical。Datadog 复现了崩溃;MongoDB 表示在特定条件下可能实现代码执行。未报告攻击,截至 2026 年 11 月 13 日不在 CISA KEV 中。
- 将每个成员升级到其分支的修复版本:4.4.32、5.0.35、6.0.30、7.0.48、8.0.37、8.3.16 或 9.0.7。Atlas 和容器参见“如何修复?”。
我受影响吗?
以下条件全部成立时,你会受到影响:
- 服务器是 MongoDB 副本集成员,包括分片集群中的分片或配置服务器副本集成员。
- 版本位于表中的某个受影响范围。
- 攻击者能够访问该成员的 MongoDB 端口,并发送携带
readConcern.afterOpTime的ping命令。在受影响版本上,服务器在检查凭据之前就接受这些请求,因此启用身份验证无法阻止准备步骤。
独立的 mongod 不受影响。它没有主节点追赶状态,也无法参与崩溃所需的选举。
崩溃还需要该成员落后于其他成员,然后赢得选举。攻击者无法促成这两件事,因此植入的 waiter 是一个在真实维护事件或故障转移时触发的陷阱。
| 分支 | 受影响版本 | 修复版本 |
|---|---|---|
| 9.0 | 9.0.0 至 9.0.6 | 9.0.7 |
| 8.3 | 8.3.0 至 8.3.15 | 8.3.16 |
| 8.0 | 8.0.0 至 8.0.36 | 8.0.37 |
| 7.0 | 7.0.0 至 7.0.47 | 7.0.48 |
| 6.0 | 6.0.0 至 6.0.29 | 6.0.30 |
| 5.0 | 5.0.0 至 5.0.34 | 5.0.35 |
| 4.4 | 4.4.0 至 4.4.31 | 4.4.32 |
MongoDB 的公告没有列出 8.2 分支,该分支已于 2026 年 7 月 31 日终止支持,不再获得修复。公开概念验证报告称,在使用仅测试用设置的实验中,8.2.12 仍会出现该缺陷。请将 8.2 视为不受支持,并迁移到已修复的分支。
检查每个成员的版本,而不仅是主节点:
# On each host, including members in containers and members that were offline
mongosh --quiet --eval 'db.version()'
# In a replica set, list every member and its state
mongosh --quiet --eval 'rs.status().members.map(m => m.name + " " + m.stateStr)'
# Docker
docker exec <container> mongosh --quiet --eval 'db.version()'
# Kubernetes, for each member pod
kubectl exec <pod> -- mongosh --quiet --eval 'db.version()'
rs.status() 在独立服务器上返回错误,这可以确认该主机不是副本集成员。对于 Atlas,请打开集群的维护设置;MongoDB 表示集群会在维护期间自动升级。
如何修复?
将每个副本集成员升级到其分支的修复版本。部分升级会让其余成员继续暴露,之后的选举可能将主节点角色转移到其中一个成员。
- 备份部署,并在供应商下载页面确认每个分支的修复版本。
- 一次升级一个成员,等它重新加入后再继续。在副本集上,先让主节点降级,或升级一个从节点,以便操作期间集合仍有主节点。
- 每次升级后在该成员上运行
db.version(),确认显示修复版本。也要检查维护窗口期间离线的成员。 - 对于 Docker,拉取修复后的镜像并重新创建容器。只替换镜像而不重新创建容器会让旧进程继续运行。公开概念验证使用
mongodb/mongodb-community-server:8.0.37-ubi9进行修复版对照测试。 - 对于 Atlas,应用待处理的维护。如果项目推迟维护,MongoDB 建议尽快应用升级。
没有服务器设置可以关闭存在漏洞的追赶路径。限制对成员的网络访问,例如仅允许应用主机和其他成员,可以减少能够植入 waiter 的客户端。这不会移除已经植入的 waiter,也不能修复竞态。仅在所有成员升级完成前保留该限制。
修复版本改变了两点。追赶回调现在只结束仍然存活且当前正在使用的追赶状态,并且只有内部用户可以发送 readConcern.afterOpTime。两者都需要:前者阻止双重清理,后者阻止客户端植入 waiter。
根本原因是什么?
主节点追赶完成回调持有追赶状态的原生指针,而该状态可能在回调运行时释放自身。因此被中止的追赶会在已释放内存上再次调用 abort_inlock()。
ReplicationCoordinatorImpl 在新当选的主节点应用其错过的操作期间保留一个 CatchupState。该状态在 _lastAppliedOpTimeWaiterList 中注册 waiter,这是一个以 OpTime 为键的 multimap。当已应用的 OpTime 达到目标时,waiter 完成,回调调用 abort_inlock() 退出追赶模式。abort_inlock() 会重置 _catchupState,从而销毁状态对象。
存在漏洞的回调忽略了完成状态,也没有检查其状态是否仍是当前状态。在 MongoDB 8.0.34 的 src/mongo/db/repl/replication_coordinator_impl.cpp 第 5267 行,回调如下:
auto targetOpTimeCB = [this](Status status) {
// Double check the target time since stepdown may signal us too.
const auto myLastApplied = _repl->_getMyLastAppliedOpTime_inlock();
if (_targetOpTime <= myLastApplied) {
...
abort_inlock(PrimaryCatchUpConclusionReason::kSucceeded);
}
};
状态由 std::unique_ptr 持有,因此对象没有共享生命周期。头文件第 1972 行声明了 std::unique_ptr<CatchupState> _catchupState;。
公开概念验证补充了缺失的步骤。两个带有对抗性 OpTime 项的 readConcern.afterOpTime waiter 会在 multimap 中形成排序循环,因此真正的追赶 waiter 永远不会被 setValueIf_inlock() 触及。下一次心跳判断成员已经追平并中止追赶。该中止重置尚未完成的 waiter,从而同步执行回调。回调再次调用 abort_inlock(),外层栈帧继续读取内层调用已释放的状态。
如何被利用?
- 攻击者向可达成员发送两个未认证的
ping命令,并携带readConcern.afterOpTime。所选的 OpTime 项使 waiter 在 multimap 中排序错误,因此真正的追赶 waiter 无法完成。 - waiter 会保留下来。它们不会过期,会一直存在到成员重启、回滚或从主节点降级。
- 该成员之后落后于另一个成员并赢得选举。攻击者无法导致滞后或选举,因此这一步依赖真实的维护事件或故障。
- 追赶结束时,清理会运行两次。新的主节点读取并写入已经释放的内存,并在接受写入前崩溃。
- Datadog 在 8.0.34 上复现了崩溃,
CatchupState::abort_inlock()处发生段错误。实验使用管理员访问权限暂停成员并强制故障转移;只有两个 ping 请求来自未认证客户端。
MongoDB 的公告称,在特定条件下该漏洞还可能允许在服务器进程中执行任意代码。Datadog 未在实验中实现代码执行,也没有声称崩溃在每个部署中都可靠。
攻击如何展开?
未认证客户端植入两个 afterOpTime waiter,之后的故障转移使该成员在落后的情况下成为主节点,追赶清理在已释放内存上运行两次。
携带 readConcern.afterOpTime"] --> B["waiter 存入
lastAppliedOpTime multimap"] B --> C["OpTime 排序使真正的
追赶 waiter 未完成"] C --> D["成员落后,
然后赢得选举"] D --> E["追赶结束,
abort_inlock() 重置 waiter"] E --> F["回调在已释放状态上
再次调用 abort_inlock()"] F --> G["新主节点在接受写入前
崩溃"]
攻击者能做什么?
未认证攻击者可以在副本集成员成为主节点的那一刻使其崩溃,从而将主节点从集合中移除,并中断写入,直到另一个成员接管。
影响取决于崩溃成员的角色:
- 普通副本集的主节点崩溃会引发选举和短暂的写入中断。如果有可用成员,它可以接管。
- 分片副本集的主节点崩溃可能会阻塞经过该分片的操作,直到选出新的主节点。
- 配置服务器的主节点崩溃可能会阻塞集群的元数据更改,直到配置服务器集合选出新的主节点。
条件也是影响的一部分:
- 攻击者需要能够访问该成员的 MongoDB 端口。
- 请求不需要账户,也不需要用户交互。
- 该成员之后必须在落后于另一个成员时赢得选举。攻击者无法强制这一点,因此崩溃是延迟陷阱,而不是立即攻击。
- 独立的
mongod不受影响。
MongoDB 表示在特定条件下该漏洞可能允许任意代码执行。没有来源证明代码执行,Datadog 的复现以崩溃结束。请将代码执行视为供应商评估,而不是已证明的能力。
为什么修复有效?
修复为追赶状态提供了共享生命周期,并让回调检查 waiter 的状态以及其状态是否仍是当前状态。回调不能再第二次运行 abort_inlock()。
MongoDB 8.0.34 与 8.0.37 之间的差异改变了所有权和回调:
- _catchupState = std::make_unique<CatchupState>(this);
+ _catchupState = std::make_shared<CatchupState>(this);
...
- auto targetOpTimeCB = [this](Status status) {
+ auto targetOpTimeCB = [weakSelf = weak_from_this()](Status status) {
+ if (!status.isOK()) {
+ return;
+ }
+ auto self = weakSelf.lock();
+ if (!self || self->_repl->_catchupState != self) {
+ return;
+ }
const auto myLastApplied = _repl->_getMyLastAppliedOpTime_inlock();
if (_targetOpTime <= myLastApplied) {
...
- abort_inlock(PrimaryCatchUpConclusionReason::kSucceeded);
+ self->abort_inlock(PrimaryCatchUpConclusionReason::kSucceeded);
}
};
头文件让 CatchupState 继承 std::enable_shared_from_this<CatchupState>,并用 std::shared_ptr 持有它。回调保留 weak_ptr,因此只能结束仍然存活且仍安装在 _catchupState 中的状态。非 OK 状态意味着另一条路径已经结束了追赶,回调直接返回,不触碰状态。
第二个修复提交 6111165c32 要求客户端提供的 readConcern.afterOpTime 具有内部用户权限。这消除了普通客户端植入 waiter 的前提。两个提交构成 8.0.37 修复;供应商为每个受影响分支列出了相应的修复版本。
如何检查是否已遭入侵?
没有报告利用,也没有发布入侵指标。这些检查在服务器日志中寻找崩溃特征和 waiter 请求。
- 查找日志 ID 51803 的
Slow query条目,对应未认证的ping,携带readConcern.afterOpTime并以MaxTimeMSExpired结束。 - 查找同一转换中成员进入主节点追赶(日志 ID 21359)后退出两次(日志 ID 21363)。
- 在这些退出之后查找指明
CatchupState::abort_inlock()的致命信号或回溯。 - 检查同一成员更早的日志。两个请求可能在故障转移之前到达,之后成为主节点的成员会保留它们。
正常选举或单次追赶退出不符合该模式。请求字段是否出现在日志中取决于日志设置,attr.remote 字段可能显示回环地址而不是客户端真实地址。失败的尝试可能不留下痕迹。
时间线
- 2026-10-30:MongoDB 编写 8.0.37 热修复的两个修复,一个针对追赶状态,一个针对
readConcern.afterOpTime。 - 2026-11-10:MongoDB 于 20:23 UTC 发布 CVE-2026-118383,并发布修复版本。两个修复提交于 23:07 和 23:09 UTC 合入。
- 2026-11-11:Datadog Security Labs 发布分析和复现,公开概念验证创建。
- 2026-11-12:The Hacker News 报道该漏洞以及 MongoDB 表示未发现利用的声明。
- 2026-11-13:CISA 的 KEV 目录未列出该 CVE。
常见问题
CVE-2026-118383 是否已在真实环境中被利用?
没有。MongoDB 表示在内部发现该漏洞,且不知道有任何利用尝试。截至 2026 年 11 月 13 日,该 CVE 不在 CISA KEV 目录中。
身份验证能阻止攻击吗?
在受影响版本上不能。两个 ping 命令在服务器检查凭据之前就被接受,因此 Datadog 能够用未认证客户端植入 waiter。8.0.37 修复会拒绝非内部用户客户端提供的 readConcern.afterOpTime。
独立的 mongod 会以这种方式崩溃吗?
不会。独立服务器没有副本集,也没有主节点追赶状态,因此导致 use-after-free 的双重清理无法运行。公告排除了独立实例。
攻击者能强制故障转移吗?
不能。攻击者可以植入 waiter,但成员必须自行落后并赢得选举。在 Datadog 的实验中,研究人员使用管理员访问权限暂停成员并触发选举;只有两个请求是未认证的。
Atlas 集群会怎样?
MongoDB 表示 Atlas 集群会在集群维护期间自动升级到修复版本。如果项目推迟维护,MongoDB 建议尽快应用升级。
我使用 8.2 分支,它已修复吗?
公告没有列出 8.2,该分支已于 2026 年 7 月 31 日终止支持。公开概念验证报告称,在使用仅测试用设置时 8.2.12 仍会出现该缺陷。请将部署迁移到受支持分支的修复版本。
用 Ostorlab 发现暴露的 MongoDB 成员
Ostorlab 攻击面发现会清点组织中面向互联网的主机和服务。用它列出你暴露的 MongoDB 端口,以便知道先升级或限制哪些成员。这是暴露主机的清单,不是对该 CVE 的检测。
参考文献
- CVE-2026-118383 记录,MongoDB CNA,2026-11-10 发布,CVSS v4.0 9.5 和 CVSS v3.1 9.0:https://www.cve.org/CVERecord?id=CVE-2026-118383(2026 年 11 月 13 日检查)
- MongoDB,“Important MongoDB security update available (Action Required) - November 10, 2026”,供应商声明和 Atlas 维护指南:https://www.mongodb.com/community/forums/t/important-mongodb-security-update-available-action-required-november-10-2026/344843(2026 年 11 月 13 日检查)
- Datadog Security Labs,“CVE-2026-118383: Use-after-free vulnerability in MongoDB”,2026 年 11 月 11 日,复现、崩溃日志和利用条件:https://securitylabs.datadoghq.com/articles/cve-2026-118383-mongodb-server-use-after-free/(2026 年 11 月 13 日检查)
- 公开概念验证和分析、两个请求的触发方式、waiter 排序循环和修复提交:https://github.com/googlesky/CVE-2026-118383(2026 年 11 月 13 日检查)
- 修复提交 23dfc542199ab3b88d6a9420b6cd3f125a897620,“SERVER-138175 [v8.0.37-hotfix] Conclude primary catch-up only from a live, current catch-up state”,2026-11-10 合入:https://github.com/mongodb/mongo/commit/23dfc542199ab3b88d6a9420b6cd3f125a897620(2026 年 11 月 13 日检查)
- 修复提交 6111165c32bfc74f197e2dfeb9480d0b52154d68,“SERVER-138119 [v8.0.37-hotfix] Allow only internal users to use readConcern.afterOpTime”,2026-11-10 合入:https://github.com/mongodb/mongo/commit/6111165c32bfc74f197e2dfeb9480d0b52154d68(2026 年 11 月 13 日检查)
- MongoDB 8.0.34 源码,
src/mongo/db/repl/replication_coordinator_impl.cpp第 5267 行的易受攻击回调和头文件第 1972 行的unique_ptr:https://github.com/mongodb/mongo/blob/r8.0.34/src/mongo/db/repl/replication_coordinator_impl.cpp(2026 年 11 月 13 日检查) - MongoDB 8.0.37 源码,修复后的回调和共享所有权:https://github.com/mongodb/mongo/blob/r8.0.37/src/mongo/db/repl/replication_coordinator_impl.cpp(2026 年 11 月 13 日检查)
- MongoDB 下载页面,修复后的 Community Server 构建:https://www.mongodb.com/try/download/community(2026 年 11 月 13 日检查)
- MongoDB 生命周期日程,8.2 于 2026 年 7 月 31 日终止支持:https://www.mongodb.com/legal/support-policy/lifecycles(2026 年 11 月 13 日检查)
- Docker Hub,官方
mongo镜像及拉取次数:https://hub.docker.com/_/mongo(2026 年 11 月 13 日检查) - CISA 已知被利用漏洞目录 JSON 订阅源,2026 年 11 月 13 日检查 CVE-2026-118383(未列出):https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json(2026 年 11 月 13 日检查)
- The Hacker News,“Critical Pre-Auth MongoDB Flaw (CVE-2026-118383) Can Crash Lagging Servers on Failover”,2026 年 11 月 12 日,Datadog 复现和供应商声明:https://thehackernews.com/2026/11/critical-pre-auth-mongodb-flaw-cve-2026.html(2026 年 11 月 13 日检查)