安全研究机构 Zero Day Initiative 报告称,7-Zip 的 MixCoder_Code 函数存在基于堆的缓冲区溢出问题,并给出 7.0 分评级。问题发生在处理 XZ 流的 filter 管道时:解码器得到的是完整输出缓冲区长度,而不是从当前位置算起的剩余空间。这个看似普通的长度计算错误,可能让攻击者借助特制压缩数据越界写入堆内存,并进一步尝试执行任意代码。
漏洞核心:容量不等于剩余空间
假设程序分配了一个 4096 字节的输出缓冲区,前面的 filter 已经写入 3000 字节。此时真正能够继续写入的空间只有 1096 字节:
缓冲区总容量:4096
当前写入位置:3000
实际剩余空间:1096
如果下一级解码器接收到的长度仍然是 4096,它可能从 buffer + 3000 开始继续写入最多 4096 字节。这样一来,写操作就可能越过已分配对象的末尾。
下面是一个用于解释边界计算的简化 C 示例。它不是 7-Zip 源码,也不能用于判断具体版本是否受影响,但能展示这类缺陷的差异:
#include <stddef.h>
#include <stdint.h>
int decode_next(uint8_t *output, size_t capacity, size_t used) {
if (used > capacity) {
return -1;
}
uint8_t *write_ptr = output + used;
size_t remaining = capacity - used;
/* 正确做法:向解码器传递 write_ptr 和 remaining。 */
return decoder_write(write_ptr, remaining);
}
危险模式则是移动了写指针,却仍传递原始容量:
/* 概念性错误示例 */
return decoder_write(output + used, capacity);
在单层解码、短输出或特定内存布局下,错误未必立刻表现为崩溃。进入多级 filter 管道后,偏移量会随处理过程变化,攻击者便可能构造输入,让某一次写入精确落到缓冲区边界之外。
从越界写到远程代码执行,中间还有条件
“可用于远程执行任意代码”不等于攻击者可以直接通过网络连接控制任何安装了 7-Zip 的机器。通常还需要一条实际的输入路径,例如用户打开或解压不可信压缩包、邮件网关自动检查附件,或者服务端任务调用 7-Zip 处理上传文件。
能否把堆溢出稳定转化为代码执行,还受到以下因素影响:
- 目标使用的 7-Zip 版本与构建方式;
- 进程权限以及是否运行在服务账户下;
- ASLR、DEP/NX、控制流保护等系统缓解机制;
- 压缩文件进入解码路径的方式;
- 进程崩溃后是否会被自动重试,以及攻击者是否能重复提交输入。
因此,风险评估不能只检查员工电脑上的桌面程序。更值得优先排查的是自动化处理链:文件上传接口、杀毒扫描前置任务、文档转换服务、CI 构建任务和邮件附件处理器。这些场景会在缺少人工确认的情况下解析外部文件,攻击面通常更直接。
可以这样实践:盘点版本并隔离不可信解压任务
来源摘要没有给出明确的受影响版本范围或修复版本,因此不要仅凭一个版本号自行推断安全状态。应同时核对 7-Zip 官方公告、软件供应商通告以及操作系统发行版的安全更新。
在 Linux 主机上,可以先定位常见命令并记录版本:
set -eu
for cmd in 7zz 7z 7za; do
if command -v "$cmd" >/dev/null 2>&1; then
echo "== $cmd =="
command -v "$cmd"
"$cmd" i 2>&1 | sed -n '1,8p'
fi
done
Windows PowerShell 可以这样检查:
$paths = @(
"$env:ProgramFiles\7-Zip\7z.exe",
"${env:ProgramFiles(x86)}\7-Zip\7z.exe"
)
foreach ($path in $paths) {
if (Test-Path $path) {
$item = Get-Item $path
[PSCustomObject]@{
Path = $path
ProductVersion = $item.VersionInfo.ProductVersion
FileVersion = $item.VersionInfo.FileVersion
}
}
}
在完成升级前,必须处理外部压缩包的 Linux 服务可以把解压步骤放进权限受限的容器。下面的示例假设当前目录包含 Dockerfile、只读输入目录 incoming 和输出目录 unpacked。
先创建镜像文件:
FROM alpine:3.20
RUN apk add --no-cache 7zip
RUN addgroup -S extractor && adduser -S -G extractor extractor
USER extractor
WORKDIR /work
ENTRYPOINT ["7z"]
然后构建镜像,并在断网、无额外 capability、限制内存和 CPU 的环境中解压:
mkdir -p incoming unpacked
chmod 700 incoming unpacked
docker build --pull -t isolated-7zip .
docker run --rm \
--network none \
--read-only \
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 512m \
--cpus 1 \
--pids-limit 64 \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
-v "$PWD/incoming:/input:ro" \
-v "$PWD/unpacked:/output" \
isolated-7zip x /input/sample.7z -o/output -y
运行前把 sample.7z 改成实际文件名,并确保镜像中的软件包已经更新到发行版提供的安全版本。容器隔离只能缩小进程被利用后的权限和可访问资源,不能修复解码器本身;内核漏洞、危险挂载和过宽权限仍可能让隔离失效。
修复时不要漏掉嵌入式调用
企业环境中的 7-Zip 不一定以独立桌面程序出现。某些产品会捆绑 7z.dll、复制命令行程序,或者把解压能力嵌入安装器和后台服务。只升级系统路径中的 7z.exe,未必会替换这些私有副本。
处置时可以按以下清单推进:
- 盘点终端、服务器、容器镜像和构建代理中的 7-Zip 可执行文件及动态库。
- 根据官方或供应商公告确认受影响范围,并升级到明确包含修复的版本。
- 暂停让高权限服务自动解压来源不明的 XZ 或压缩文件。
- 将文件解析任务放入低权限、断网、有限资源的沙箱或容器。
- 检查解析服务近期的异常退出、堆损坏记录和重复提交的可疑压缩包。
- 升级后重新构建基础镜像和应用镜像,避免旧二进制继续留在镜像层中。
这类漏洞再次说明,压缩工具不是无害的文件搬运程序,而是直接解析攻击者可控二进制格式的复杂解析器。补丁是首要措施;权限收缩、输入隔离和资产盘点则决定了下一次解析漏洞出现时,影响会停留在一个失败任务,还是扩展到整台主机。