libarchive解析死循环漏洞CVE-2026-4111
libarchive 是跨平台、高性能开源 C 语言库,专注于流式处理多种归档与压缩格式,是系统工具、包管理器、备份软件的底层核心组件。
一、基本情况
libarchive 是一个跨平台 C 库,广泛用于读取和写入多种归档及压缩格式(如 tar, zip, rar 等),通过插件支持 zstd、lz4 等等现代算法。

libarchive 采用纯 C 实现,无外部依赖,可静态/动态链接,适合嵌入式与服务器场景,内置gzip、bzip2、xz、lzma、lzip、compress。
栋科技漏洞库关注到 libarchive 中存在的 RAR5 解析死循环漏洞,该漏洞现在已经被追踪为CVE-2026-4111,漏洞的CVSS 3.X评分7.5。
二、漏洞分析
CVE-2026-4111漏洞是一个位于 libarchive 的 RAR5 归档解压逻辑实现的 archive_read_data() 处理路径中存在无限循环拒绝服务漏洞。
由于筛选器激活阈值和半窗口输出限制器间的逻辑死锁,漏洞发生在archive_read_support_format_rar5.c中的unpress_file()例程中。
通过archive_read_data()处理特制RAR5存档,解压缩器将进入一种既不能满足过滤器激活条件也不能满足输出窗口进度条件的状态。
这种状态会导致循环无限期地继续,并持续消耗大量的 CPU 资源,甚至是消耗100%的CPU。
此类恶意归档通过了所有CRC和校验和验证,受影响应用在处理前无法识别,导致看似有效存档触发漏洞而无需身份验证或用户交互。
因此,可被攻击者利用耗尽自动提取或扫描存档的应用程序中的工作线程,或者对自动处理归档的服务发起持续拒绝服务(DoS)攻击。
1、片段 1 - 半窗口限制器(位于 do_uncompress_block () 函数,约第 3143 行)
if (write_ptr - last_write_ptr > (window_size >> 1)) {
peak; // don't decode more than half a window per call
}
这是为了防止无限制使用内存。当 window_size = 128KB 时,每次调用的限制为 65536 字节。
2、片段 2 - 过滤器激活(apply_filters (),约第 774 行):
仅当解压器的 write_ptr 达到 block_start + block_length 时,过滤器才会触发。
在过滤器触发之前,由于过滤器不让数据流向使用者,last_write_ptr 会一直停留在 block_start。
3、片段 3 - 重试循环(uncompress_file (),约第 3965 行):
while(1) {
ret = do_uncompress_file(a);
if (ret != ARCHIVE_RETRY)
return ret;
}
4、当块长度为 70000 字节,但半窗口限制为 65536 字节时会发生以下情况:
(1)解压器解码 65536 字节,达到半窗口限制,退出循环
(2)apply_filters () 检查:write_ptr 是否达到 block_start + 70000?未达到 —— 还差 4464 字节。
过滤器不触发。last_write_ptr 保持不变。
(3)下一次迭代:write_ptr - last_write_ptr 已为 65536 → 立即触发半窗口限制 → 未解码任何新字节
(4)过滤器仍无法触发 → 返回 ARCHIVE_RETRY
(5)uncompress_file () 回到步骤(3)无限循环。
5、解压器无法继续执行,因为它无法解码超过半窗口间隙的数据。
过滤器无法触发,因为已解码的数据不足。流程停滞。无限返回 ARCHIVE_RETRY。
6、验证缺口位置
parse_filter ()(约第 3040 行)对块长度进行合理性检查:
if (block_length < 0 || block_length > 0x400000)
return ARCHIVE_FATAL;
4MB 的上限旨在拦截无意义的非法值,但并未考虑 block_length 与 window_size 之间的关联关系。
最小窗口为 128KB(半数为 64KB),因此任何大于 65537 的 block_length 都会造成死锁。
PoC 中使用的 70000 远低于 4MB,顺利通过了校验。
三、影响范围
libarchive ≤ 3.7.2
四、修复建议
libarchive ≥ 3.7.3
五、参考链接
管理员已设置登录后刷新可查看