不乱于心,不困于情。
不畏将来,不念过往。如此,安好。

7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)

图1–7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)–seo优化_前端开发_渗透技术

导语:2026年4月,GitHub安全实验室(GitHub Security Lab,GHSL)向7-Zip项目提交了一份重量级漏洞报告。攻击者精心构造一个NTFS镜像文件,用户在7-Zip中打开即触发堆溢出,最终实现远程代码执行。这个漏洞有多危险?CvSS评分8.8,国内用户海量,紧急预警。


一、漏洞概述

GHSL(GitHub安全实验室)安全研究员Jaroslav Lobačevski(JabLob)发现了这个漏洞,编号为GHSL-2026-140,分配CVE编号CVE-2026-48095

漏洞位于7-Zip处理NTFS压缩流的核心逻辑中,根因是一个32位移位未定义行为(shift UB)。当攻击者构造特定的NTFS镜像时,触发GetCuSize()函数计算出错误的缓冲区大小,导致堆溢出——256 MB的攻击者可控数据被写入一个1字节的堆缓冲区,最终实现vtable劫持和代码执行。

影响版本:7-Zip 26.00及此前所有支持NTFS压缩流的功能版本

修复版本:7-Zip 26.01(2026年4月27日发布)。


二、技术分析

2.1 根因:GetCuSize()移位越界

漏洞入口在CInStream::GetCuSize()函数(CPP/7zip/Archive/NtfsHandler.cpp第687行):

UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }

这个函数计算NTFS压缩单元的缓冲区大小。正常情况下,结果作为_inBuf_outBuf的分配大小。

问题来了:当NTFS镜像同时满足以下两个条件时,移位指数达到32:

此时,BlockSizeLog + CompressionUnit = 28 + 4 = 32,而(UInt32)1 << 32在C++标准中是未定义行为。

在x86和x64架构上,由于硬件对移位计数的掩码机制,这个UB通常让结果为1——也就是说,_inBuf被分配为1字节的堆空间。

2.2 堆溢出:1字节缓冲区写入256 MB

分配完1字节的_inBuf后,代码立即尝试往里面读入压缩数据:

// NtfsHandler.cpp, lines 940-941const size_t compressed = (size_t)numChunks << BlockSizeLog; // up to 256 MBRINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed)) // 写入1字节缓冲区!

compressed最大可达256 MB(当numChunks = 1、BlockSizeLog = 28时),而目标缓冲区只有1字节。这是典型的堆缓冲区溢出。

2.3 vtable劫持:代码执行路径

关键在于_inBuf的内存布局。调试分析(release /O1构建)显示,CInStream流对象紧邻_inBuf分配在堆上,二者之间仅相隔304字节(0x130)。

攻击流程如下:

  1. 第一次Read()迭代写入64 KB数据,从起始位置开始向高地址蔓延
  2. 写入304字节后,覆盖流对象的vtable指针
  3. 第二次Read()迭代通过被篡改的vtable分派,虚函数调用直接跳转至攻击者控制的地址
  4. 攻击者通过NTFS镜像的群集内容完全控制写入数据,也即控制了vtable指针的值

这就是经典的**vtable劫持(vtable hijack)**攻击链,从堆溢出到代码执行一气呵成。

2.4 平台行为差异

32位构建:size_t为32位,(size_t)2 << 32同样触发UB,结果为2。_inBuf.Alloc(1)_outBuf.Alloc(2)均成功,堆溢出无条件触发

64位构建(size_t)2 << 32是合法的64位移位,结果为8 GB。_outBuf.Alloc(8 GB)在拥有足够内存的系统上成功(实测64 GB内存机器通过),然后继续执行到同样的堆溢出。在低内存系统上分配可能抛出CNewException,退化为拒绝服务。

2.5 攻击面:不止于.ntfs和.img

这是最容易被忽视的致命细节。7-Zip使用签名兜底检测机制:当按文件扩展名匹配的处理程序失败后,会按签名优先级依次尝试所有剩余处理程序。

NTFS处理程序在字节偏移3处匹配"NTFS "签名(NtfsHandler.cpp:2889处的REGISTER_ARC_I)。因此,一个精心构造的NTFS镜像可以用任意扩展名——.7z、.zip、.rar或无扩展名——在扩展名匹配失败后被NTFS处理程序打开。

这意味着,即使用户"只是打开一个.zip文件",如果文件实际上是伪装的NTFS镜像,攻击同样生效。用户不需要任何交互,点击即中。


三、漏洞验证与PoC

GHSL提供了完整PoC脚本gen_ntfs_sparse.py,核心构造如下:

# 引导扇区:ClusterSizeLog = 28boot[13] = 0xED  # SectorsPerCluster编码,映射为ClusterSizeLog = 28# MFT记录:构造压缩$DATA属性,CompressionUnit = 4a[0x22] = 4  # CompressionUnit = 4

运行后会生成poc_ntfs_sparse.ntfs——一个512 MB的稀疏NTFS镜像(实际数据约8 KB)。用户只需用7-Zip 26.00打开该文件,漏洞即触发。

PoC链接(来自GHSL官方公告):https://securitylab.github.com/advisories/GHSL-2026-140_7-Zip/

GHSL还使用**UBSan(未定义行为 sanitizer)**在Linux x64上确认了漏洞根因:

../../Archive/NtfsHandler.cpp:687:47: runtime error: shift exponent 32 is too large for 32-bit type 'UInt32' (aka 'unsigned int')

随后触发SEGV(访问零页),验证崩溃路径。


四、影响范围与修复

受影响版本:GetCuSize()计算逻辑自NTFS压缩流支持引入以来一直存在,所有版本至26.00均受影响。

修复方案:升级至7-Zip 26.01。官方已于2026年4月27日发布修复版本,下载链接:

https://sourceforge.net/p/sevenzip/discussion/45797/thread/555e132ba4/

CVSS评分:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — 8.8(高危)

指标 评分 说明
AV N 网络可达,无需本地
AC L 低复杂性,无需特殊条件
PR N 无权限要求
UI R 需用户打开文件(但无二次确认)
S U 不影响其他范围
C/I/H H 机密性/完整性/可用性全高

五、检测与缓解

临时缓解措施

检测方案


六、总结

CVE-2026-48095是一个教科书级别的堆溢出漏洞:从数学上的移位未定义行为,到堆布局精心策划的溢出,再到vtable劫持——整条攻击链不过几百行代码,却能实现点击即RCE。

特别值得强调的是攻击面之广:用户以为自己在打开一个普通的.zip文件,实际上触发的是NTFS处理程序,而NTFS处理程序根本没有出现在文件扩展名关联列表中。这种"签名兜底"的默认行为,让每一个来源不明的压缩文件都可能成为武器。

国内7-Zip用户海量,很多打包工具、PE工具甚至系统镜像工具都依赖7z.dll。这个漏洞的修复窗口期至关重要——立即升级到26.01是唯一的解法。


图2–7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)–seo优化_前端开发_渗透技术

图3–7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)–seo优化_前端开发_渗透技术

图4–7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)–seo优化_前端开发_渗透技术

图5–7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)–seo优化_前端开发_渗透技术


赞(0)
未经允许不得转载:seo优化_前端开发_渗透技术 » 7-Zip 26.00堆溢出RCE漏洞分析(CVE-2026-48095)