MongoBleed漏洞深度解析:潜伏八年的内存泄露危机

admin 2026-01-01 05:15:52 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: MongoBleed漏洞CVE-2025-14847允许未认证攻击者读取MongoDB堆内存数据,影响自2017年以来版本。攻击者利用zlib压缩处理缺陷窃取敏感信息。建议立即更新补丁或禁用zlib压缩。 综合评分: 96 文章分类: 漏洞分析,漏洞预警,应用安全


cover_image

MongoBleed 漏洞深度解析:潜伏八年的内存泄露危机

Stanislav

securitainment

2025年12月31日 10:24 中国香港

MongoBleed(正式编号 CVE-2025-14847) 是近期曝光的一个高危漏洞,几乎影响自 2017 年以来的所有 MongoDB 版本。

该漏洞存在于 MongoDB 的 zlib消息压缩处理路径中。

攻击者可利用此漏洞读取任意未初始化的堆内存数据——这意味着先前数据库操作遗留在内存中的任何信息都可能被窃取。

该漏洞自 2017 年被引入代码库后便一直存在。由于利用门槛极低,攻击者只需能够连接数据库即可发起攻击 (无需任何身份认证)。目前该漏洞已被修复,但部分已终止支持的版本 (3.6、4.0、4.2) 将不会获得补丁。

MongoDB 基础知识

在深入漏洞原理之前,我们先了解一些基础概念:

  • MongoDB 使用自定义的 TCP 有线协议,而非 HTTP 等通用协议。这在追求高性能的数据库中很常见。
  • MongoDB 使用 BSON 格式传输消息。BSON 本质上是二进制化的 JSON,但做了一些关键优化。稍后我们会详细讨论其中一项优化,因为它对漏洞利用至关重要。
  • MongoDB 没有端点或 RPC 的概念,只使用一个名为 OP_MSG 的操作码。
  • OP_MSG 命令包含一个 BSON 消息,消息内容决定了请求类型。具体来说,消息的第一个字段标识请求类型。
  • 请求可以被压缩。这种情况下,会发送一个 OP_COMPRESSED 消息来包装压缩后的 OP_MSG BSON 数据。
  • 压缩后的请求结构如下:
     OP_COMPRESSED 消息
┌────────────────────────────┐
│ 标准头部 (16 字节)          │
├────────────────────────────┤
│ originalOpcode (int32)     │
│ uncompressedSize (int32)   │
│ compressorId (int8)        │
│ 压缩后的 OP 载荷            │
└────────────────────────────┘
  • 关键点在于,uncompressedSize字段声明了载荷解压后的大小。

漏洞利用 – 第一部分

漏洞利用的第一步是诱使服务器误判即将收到一个超大的 OP_MSG。

攻击者可以发送一个虚假的超大 uncompressedSize字段值,比如 1MB,而实际解压后的消息只有 1KB。

这会使服务器分配一个 1MB 的缓冲区来存放解压后的消息。到目前为止一切正常。

但关键问题在于:解压完成后,服务器并不检查实际解压出来的数据大小。

相反,它直接信任用户的输入,将其作为载荷的实际大小,即使真正解压出来的大小不同。

结果就是在内存中形成了这样的 BSON 消息结构:

[ 1KB 真实数据 |      999KB 未引用的堆内存垃圾数据       ]
                   ↑                                               ↑
        实际长度 (1KB)                     用户声明长度 (1MB)

未引用的堆内存垃圾数据

与所有编程语言类似,当代码中的变量超出作用域时,运行时会将其占用的内存标记为可用。

在大多数现代语言中,内存会被清零——也就是说,原来占用该空间的旧数据会被删除。

但在 C/C++ 中情况不同。当你通过 malloc()分配内存时,得到的是之前遗留在那里的任何数据。

由于 MongoDB 是用 C++ 编写的,这部分未引用的堆内存垃圾可能包含先前操作的任何数据,包括:

  • 明文密码和凭证
  • 会话令牌 / API 密钥
  • 客户数据和个人身份信息 (PII)
  • 数据库配置和系统信息
  • Docker 路径和客户端 IP 地址
[ 真实 BSON 数据 | password: 123 | apiKey: jA2sa | ip: 219.117.127.202 ]

漏洞利用 – 第二部分

现在服务器已经错误地将一些潜在敏感数据分配到了输入消息中,攻击者只需设法让服务器将这些数据返回即可。

BSON 格式

如前所述,BSON 是 MongoDB 序列化 JSON 的方式。正如其官网所述,BSON 的设计以效率为核心:

3. 高效

由于使用了 C 数据类型,大多数语言都可以非常快速地完成 BSON 的编码和解码。

C 语言字符串

C 语言使用著名的空字符结尾字符串。空字符结尾字符串意味着使用空字节来标记字符串的结束:

char* s = "hello"
// 在内存中,这被表示为一个字符数组,最后一个元素是空终止符:h e l l o \0

解析这类字符串的方式很简单——反序列化器读取每个字符,直到找到空终止符为止。

恶意 BSON 输入

前面提到过,BSON 消息的第一个字段决定了命令的 “RPC” 类型。

因此,服务器处理网络请求时首先要做的就是……解析第一个字段!

由于字段是字符串,而字符串是空字符结尾的 C 字符串,MongoDB 服务器的反序列化逻辑会持续解析字段直到找到第一个空终止符。

攻击者可以发送一个压缩的、无效的 BSON 对象,该对象不包含空终止符。这迫使服务器继续扫描错误分配的内存缓冲区中的外部数据,直到找到第一个空终止符 (\0)。

# 概念示意
[ 真实数据 |             未引用的堆内存垃圾                 ]
# 实际示例
[ { "a      | password: 123\0 | apiKey: jA2sa | ip: 219.117.127.202 ]

由于第一个空终止符恰好在密码之后,服务器此时会认为 BSON 的第一个字段是:

"a      | password: 123"

显然这是一个无效的 BSON 字段名,所以服务器会向客户端返回错误响应。为了提供帮助,错误消息中包含了无效字段名的具体内容:

{
"ok": 0,
"errmsg": "invalid BSON field name 'a      | password: 123'",
"code": 2,
"codeName": "BadValue"
}

完美。攻击者成功让服务器泄露了数据。

任何认真的攻击者都会反复执行这一操作,每秒数千次,直到他们认为已经扫描了数据库堆内存的大部分内容。然后可以无限重复这个过程。


💥 影响

1. 利用难度极低——”预认证”攻击

这个漏洞的影响尤其恶劣,因为请求 – 响应的解析过程发生在任何身份认证之前。这是合理的,因为你无法对尚未反序列化的请求进行认证。

这使得任何攻击者都能获取任何潜在敏感数据。他们唯一需要的就是能够通过互联网访问数据库。

将数据库暴露在互联网上是一种被强烈反对的做法。然而,Shodan 显示目前有超过 213,000 个公开可访问的 MongoDB 数据库。

2. 八年的漏洞窗口期 (处理不当)

引入这个漏洞的 PR 来自 2017 年 5 月。这意味着从大约 3.6.0 版本开始,任何公开可访问的 MongoDB 实例都存在此漏洞。

目前尚不清楚在漏洞披露之前是否已被恶意行为者发现并利用。鉴于其利用门槛之低,我认为很可能已被利用过。

该漏洞于 12 月 19 日披露后,修补数据库的竞赛便开始了。

通过查阅 Git 历史,修复代码似乎最初于 12 月 17 日提交。有趣的是,直到整整 5 天后的 12 月 22 日才被合并 (顺便说一句,只是一行代码的修复)。

话虽如此,包含修复的 MongoDB 8.0.17 于 12 月 19 日发布,与 CVE 发布日期一致。但 JIRA 活动显示补丁是在 12 月 22 日推出的。

由于没有官方时间线公布,像我这样的社区成员只能猜测。截至撰写本文的 2025 年 12 月 28 日,即事发 10 天后,MongoDB 仍未正式公开回应此问题。

他们在 CVE 发布整整五天后才发布了一份社区公告。直到 12 月 24 日,他们才宣布其云服务 Atlas 中的所有数据库实例已全部完成修补。

我认为这意味着所有暴露在互联网上的 Atlas 数据库在近一周内都存在此漏洞。默认情况下,Atlas 数据库使用 IP 白名单进行连接控制,但用户可以将其配置为允许来自任何地方的连接。

MongoDB 表示目前尚未发现被利用的证据:

“目前,我们没有证据表明此问题已被利用或任何客户数据已被泄露”

3. 缓解措施简单

值得庆幸的是,缓解措施非常简单,有两个选择:

  1. 更新到最新补丁版本
  2. 禁用 zlib 网络压缩

我发现后者在网络讨论中传播不多,但据我了解,作为短期缓解措施同样有效。


一点小插曲

Elastic 的安全技术负责人通过发布一个 Python 概念验证脚本,为这个漏洞取名为 MongoBleed: https://github.com/joe-desimone/mongobleed

https://cyberplace.social/@GossiTheDog/115786817774728155

Joe Desimone@dez_

🎅mongobleed – CVE-2025-14847 的 PoC。由于 zlib 消息解压缺陷,可从 MongoDB 实例泄露数据。令人想起 Heartbleed ❤️

2025 年 12 月 26 日 上午 8:39 · 68.6K 次浏览

11 条回复 · 109 次转发 · 554 次点赞

原推文链接

这一点特别有趣,因为尽管是不同的系统,MongoDB 与 Elastic 在向量搜索、文本搜索和分析等场景上存在竞争关系。


总结

  • 该漏洞允许攻击者读取任意堆内存数据,包括用户数据、明文密码、API 密钥等。
  • 攻击通过构造一个简单的畸形 zlib 压缩请求来实现。
  • 2017 年至 2025 年间的 MongoDB 版本均受此漏洞影响。
  • 大致时间线:
  • 2017 年 6 月 1 日:引入漏洞的提交被合并。
  • 2025 年 12 月 17 日:修复代码编写完成 (原始提交日期)。
  • 2025 年 12 月 19 日:CVE 正式发布。
  • 2025 年 12 月 22 日:修复代码被合并。
  • 2025 年 12 月 24 日:MongoDB 发布补丁公告,宣称所有 Atlas 数据库已完成修补。
  • 12 月 24 日,MongoDB 报告称没有证据表明有人利用此 CVE。考虑到这个漏洞存在了约 8 年,而且他们的云服务 Atlas 在 CVE 正式发布后花了整整 5 天才完成修补……我对此表示怀疑。
  • MongoDB 尚未就此事道歉。
  • 目前有超过 213,000 个可能存在漏洞的互联网暴露 MongoDB 实例,确保这个漏洞真正达到了 web scale

相关链接

  • 官方 CVE: https://nvd.nist.gov/vuln/detail/CVE-2025-14847 (2025 年 12 月 19 日)
  • 引入漏洞的 PR: https://github.com/mongodb/mongo/pull/1152 (2017 年 5 月)
  • 修复问题的提交:https://github.com/mongodb/mongo/commit/505b660a14698bd2b5233bd94da3917b585c5728#diff-e5f6e2daef81ce1c3c4e9f7d992bd6ff9946b3b4d98a601e4d9573e5ef0cb07dR77
  • 事件安全报告,包含修复版本信息:https://www.ox.security/blog/attackers-could-exploit-zlib-to-exfiltrate-data-cve-2025-14847/
  • 通过日志分析检测利用尝试的文章:https://blog.ecapuano.com/p/hunting-mongobleed-cve-2025-14847
  • 有人还用 vibe-coding 写了一个检测器:https://github.com/Neo23x0/mongobleed-detector

MongoBleed explained simply

免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:securitainment Stanislav《MongoBleed 漏洞深度解析:潜伏八年的内存泄露危机》

Jadx也想要翅膀 网络安全文章

Jadx也想要翅膀

文章总结: 本文介绍利用AI增强Jadx逆向效率,通过配置jadx-ai-mcp插件及MCP服务器,实现AI辅助定位Android应用Token生成逻辑并编写F
评论:0   参与:  0