文章归档 / 漏洞分析

7-Zip XZ 分块解码堆缓冲区溢出漏洞(CVE-2026-14266)

分析 7-Zip 26.01 在 XZ 多 filter 分块解码中未扣减 outWritten 导致的堆越界写,并基于 26.02 diff、IDA 反编译和 PoC 对照验证修复效果。

PUBLISHED
2026.07.17
READING
7 MIN
SECTIONS
05
VIEWS
文章目录05 SECTIONS

实验说明: 本文仅记录授权测试环境中的漏洞复现与逆向分析过程。请勿对未授权目标投递或诱导解析测试样本;建议在隔离虚拟机中完成验证。

基本信息

  • CVE 编号:CVE-2026-14266
  • 漏洞标题:7-Zip XZ 分块解码堆缓冲区溢出漏洞
  • 厂商:7-Zip / Igor Pavlov
  • 产品:7-Zip
  • 漏洞类型:CWE-122 Heap-based Buffer Overflow
  • CVSS:7.0,CVSS:3.0/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H,来源为 ZDI-26-444
  • Disclosure Date:2026-07-15,ZDI 协调公开;2026-06-05 报告给厂商;2026-06-25 7-Zip 26.02 发布修复
  • 修复版本:7-Zip 26.02

漏洞描述

CVE-2026-14266 是 7-Zip 处理 XZ 压缩流时的堆缓冲区溢出漏洞,触发点位于 C/XzDec.c 的 MixCoder_Code。受影响版本在 p->outBuf 单缓冲路径处理多 filter XZ block 时,会把本轮 LZMA2 解码可写容量设置为完整 destLenOrig,而不是扣除已经累计写入的 p->outWritten。若 XZ block 使用 BCJ + LZMA2 等多 filter 组合,并且分块头部声明的 UnpackSize 小于实际 LZMA2 输出推进量,LZMA2 层会基于过大的 destLen2 计算 dicLimit,最终向 outBuf 分配范围之后继续写入。

攻击者可构造恶意 XZ 文件或包含 XZ 数据流的归档,让目标用户使用 7-Zip 26.01 打开、测试或解压该文件。ZDI 将该问题描述为远程代码执行,前提是用户访问恶意页面或打开恶意文件;本地验证中,恶意 XZ 在 26.01 上触发 EXCEPTION_ACCESS_VIOLATION 写访问崩溃,在 26.02 上转为 Data Error。基于当前证据,漏洞本质为可由文件内容触发的堆越界写,RCE 影响以 ZDI 公告为准,本地稳定 RCE 链未纳入本报告验证结论。

修复方案

官方修复

Windows 静默安装命令:

cd C:\Users\hz\Downloads
Invoke-WebRequest -Uri "https://www.7-zip.org/a/7z2602-x64.exe" -OutFile ".\7z2602-x64.exe"
Start-Process -FilePath ".\7z2602-x64.exe" -ArgumentList "/S" -Wait
& "$env:ProgramFiles\7-Zip\7z.exe" | Select-Object -First 3

winget 环境命令:

winget upgrade --id 7zip.7zip --version 26.02
& "$env:ProgramFiles\7-Zip\7z.exe" | Select-Object -First 3

Linux 源码包更新命令示例:

mkdir -p /opt/7zip-26.02 && cd /opt/7zip-26.02
curl -LO https://www.7-zip.org/a/7z2602-src.tar.xz
sha256sum 7z2602-src.tar.xz
# 期望:cf967c98bca02a4b8b16375f441825a8e141362f14be1969bbec8e1ca0bff9dd

漏洞分析

Attack Path: 本地

Applicable OS: 跨平台

Outbound Connection Required:

Vulnerability Location: 源码位置 C/XzDec.c::MixCoder_Code;Windows 二进制位置 7z.dll,26.01 中对应 IDA 函数 sub_10130670,26.02 中对应 IDA 函数 sub_1012FFE0。

Root Cause: 26.01 在 p->outBuf 为真且 p->numCoders != 1 的路径中,第一层 coder->Code2 调用收到的 destLen2 等于完整 destLenOrig。多轮解码时 p->outWritten 已经大于 0,但下一轮仍按完整 outBuf 容量传入 LZMA2。LZMA2 侧使用 dicLimit = dicPos + *destLen 推进字典写入边界,因此 dicLimit 可越过真实 outBufSize。26.02 修复为在多 coder 情况下先比较 destLen2 与 p->outWritten,异常时返回 SZ_ERROR_FAIL,正常时执行 destLen2 -= p->outWritten,仅把剩余容量交给第一层 coder。

26.01 关键逻辑:

srcLen2 = srcLenOrig;
destLen2 = destLenOrig;
res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, &p->status);
p->outWritten += destLen2;

26.02 修复逻辑:

destLen2 = destLenOrig;
if (p->numCoders != 1)
{
  if (destLen2 < p->outWritten)
    return SZ_ERROR_FAIL;
  destLen2 -= p->outWritten;
}
*srcLen = srcLenOrig;
res = coder->Code2(coder->p, NULL, &destLen2, src, srcLen, srcWasFinished, finishMode, &p->status);
p->outWritten += destLen2;

26.02 的 MixCoder_Code 新增以下汇编检查,字段映射为 [rbx+10h] = p->numCoders,[rbx+28h] = p->outWritten,eax=0Bh = SZ_ERROR_FAIL:

cmp     dword ptr [rbx+10h], 1
jz      short loc_101300AB
mov     rcx, [rbx+28h]
cmp     rax, rcx
jnb     short loc_1013009B
mov     eax, 0Bh
jmp     loc_1013043E
sub     rax, rcx

漏洞复现

目标版本:7-Zip 26.01 x64 Windows。

PoC:hg0434hongzh0/CVE-2026-14266

END OF RESEARCH NOTE

最后更新于 2026.07.17 · hongzh0's Blog