
MongoDB Server 中的一个严重漏洞允许未认证的攻击者发送两个请求,从而触发数据库服务器崩溃。只有当该服务器随后被选为接管主服务器、而它仍缺少一些近期变更时,崩溃才会发生。
开发该数据库的公司 MongoDB 于本周早些时候发布了修复版本。
受影响的服务器是副本集的成员,副本集是一组保存同一数据副本的 MongoDB 服务器。其中一个成员作为 primary(主节点),充当主服务器并处理所有新的写入,其他成员则复制这些写入。如果 primary 不可用,其他成员会举行选举以选出新的 primary。
Datadog Security Labs 的研究人员在实验室中复现了该崩溃,并于昨天公布了他们的发现。在受影响版本上,开启认证并不能阻止这两个请求。研究人员表示,攻击者无法让目标成员落后或赢得选举,也无法看到这两种情况何时发生。
该漏洞编号为 CVE-2026-118383,属于 use-after-free:服务器最终使用了已经释放的内存。MongoDB 在 CVSS 4.0 严重性评分中给它打了 9.5 分(满分 10 分)。该公司表示,该漏洞是它自己发现的,并且“未发现任何利用此漏洞的尝试”。
受影响的成员包括分片集群中的 shard 和 config server 成员。独立的 mongod(不在任何副本集中的单个服务器)不受影响。
每个受影响的分支都有一个修复版本,列于下方以及 CVE 记录中。一个分支中此前的所有版本都受影响,最早可追溯至该分支的首个版本。
MongoDB 在其安全公告中表示,MongoDB Atlas 集群会在维护期间自动收到修复版本。推迟维护的客户应尽快应用升级。
自管理部署需要在每个副本集成员上安装修复版本。升级后,请检查每个成员正在运行的版本,包括容器中的成员以及维护期间处于离线状态的成员。
8.2 分支不在所列的受影响版本之中,其最新版本为 8.2.12。但发布在 GitHub 上的一个概念验证报告称,在使用仅用于测试的设置的实验室测试中,8.2.12 仍表现出该缺陷。
根据该公司的生命周期时间表,8.2 分支已于 7 月 31 日停止支持。过了该日期,版本将不再获得修复,包括安全修复。
在成员能够升级之前,研究人员建议将数据库的网络访问限制为仅允许需要它的系统。这限制了谁可以发送这两个请求,但并不能修复该漏洞。

赢得选举的成员会先通过应用它错过的写入来追赶进度,然后才接受新的写入。根据 Datadog 研究人员的技术分析,该漏洞存在于这一追赶步骤结束时执行的清理过程中。
这两个请求是携带 readConcern.afterOpTime 值的 ping 命令。每个请求都要求服务器等待复制到达某个时间点,服务器会为此记录一个待处理通知,称为 waiter。
植入这些 waiter 并不会使服务器崩溃。它们不会过期,并会一直保留,直到该成员重启、回滚或从 primary 降级。
严重预认证 MongoDB 缺陷(CVE-2026-118383)可在故障转移时使落后的服务器崩溃
崩溃需要接收这些请求的成员在之后赢得选举,即使它落后于另一个成员。当追赶结束时,清理会运行两次,复用已经释放的内存,新的主节点在接收任何写入之前崩溃。研究人员表示,一旦满足这些条件,崩溃并不依赖于赢得时序竞争。
在实验室中,研究人员使该成员落后,并通过使用管理员访问权限暂停和停止 mongod 进程,自己强制触发了故障转移。只有这两个请求来自一个没有凭据的客户端,而且该客户端无法写入数据库。
在 8.0.34 版本上,该成员因段错误崩溃,使实验室集群没有主节点。另一个部署可能会选举出新的主节点并继续运行。
在修复后的 8.0.37 版本中,服务器立即以未授权为由拒绝了这两个请求,该成员继续运行。修复的一部分只允许系统用户使用 readConcern.afterOpTime。
MongoDB 表示,在某些条件下,该缺陷还可能导致服务器进程中发生任意代码执行。不过,研究人员表示,在实验室中,“我们并未实现代码执行”。他们的结果也没有显示该攻击在其他环境中会有多高的成功率。
据其作者称,该概念验证代码在实验室副本集中复现了该缺陷。其可靠模式需要一项仅用于测试的设置,远程攻击者无法启用。其声明的影响是崩溃或内存损坏,并未声称可实现代码执行。
研究人员表示,修复的第二部分阻止清理在等待者已经就位的情况下仍运行两次。他们自己没有测试这一部分。
在关闭身份验证的情况下运行的概念验证实验室测试中,修复后的 8.0.37 接受了植入的等待者,但只运行了一次清理。
要查找植入或崩溃,请检查服务器的结构化日志,寻找研究人员在存在漏洞的运行中的这些迹象:
- 日志事件:一条 COMMAND "Slow query" 条目(ID 51803),对应一个携带 readConcern.afterOpTime 且以 MaxTimeMSExpired 结束的未认证 ping。
- 日志事件:一个成员进入主节点追赶(ID 21359),然后在一次转换中两次退出该状态(ID 21363)。
- 日志事件:在这些退出之后出现涉及 CatchupState::abort_inlock() 的致命信号或回溯。
正常的选举或单次追赶退出并不指向该缺陷。这些请求也可能在故障转移之前到达,因此还要检查同一成员更早的日志。
请求字段是否被记录取决于日志设置,attr.remote 字段可能显示回环地址,而不是客户端的真实 IP。