0x01 概述
Apache Commons Compress是一个开源的Java组件,用于处理各种压缩和归档格式,如ZIP、Tar、7z、gzip、bzip2等等。它提供了一套简单而灵活的API,使开发人员能够在Java应用程序中轻松地创建、解压缩和操作各种压缩格式的文件。
笔者通过对数百个真实项目引入组件的分析选出了Commons Compress组件的常见漏洞进行分析。本次分析的是CVE-2021-35516,Commons Compress对7z压缩文件解压时造成的内存耗尽漏洞。
0x02 组件使用场景
Apache Commons Compress组件广泛应用于Java开发中,可用于创建、解压多种压缩格式的文件,适用于文件压缩、归档管理、数据导出、备份、日志归档、安装程序创建、在线文件处理以及数据存档等场景,为开发人员提供了处理压缩和归档文件的便捷功能。
0x03 漏洞信息
3.1.1 漏洞简介
- 漏洞名称:内存耗尽漏洞
- 漏洞编号:CVE-2021-35516
- 漏洞类型:CWE-770 不受限制的分配资源
- CWE-130 长度参数处理不当
- CVSS评分:CVSS v3.1:7.5
- 漏洞危害等级:高危
3.1.2 漏洞概述
当读取一个特制的7Z归档文件时,Commons Compress库可能会被迫分配大量内存,最终导致即使对于非常小的输入也会出现内存不足错误。这可能被用于对使用Commons Compress库的7z包的服务发起拒绝服务攻击。
3.1.3 漏洞利用条件
使用的Apache Commons Compress为漏洞影响版本。
3.1.4 影响版本
Apache Commons Compress 1.6 ~ 1.20
3.1.5 漏洞分析
1.样本分析
样本如下,可以发现Start Header全0。
2.补丁分析
其补丁对文件的内容进行了合法性检查,并且在修复文档中表示readFilesInfo使用了惰性延迟分配以避免出现内存不足的问题,但是仍不能具体找到漏洞的触发点。
3.动态分析
构造测试代码,执行。
package org.example;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Unzip7zExample {
public static void main(String[] args) {
String sevenzFilePath = ""; // 指定要解压的7z文件路径
String outputFolder = ""; // 指定解压后的输出文件夹路径
try {
unzip7z(sevenzFilePath, outputFolder);
System.out.println("Unzip successful!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unzip7z(String sevenzFilePath, String outputFolder) throws IOException {
try (SevenZFile sevenZFile = new SevenZFile(new File(sevenzFilePath))) {
SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (!entry.isDirectory()) {
File entryFile = new File(outputFolder, entry.getName());
File entryParent = entryFile.getParentFile();
if (entryParent != null && !entryParent.exists()) {
entryParent.mkdirs();
}
try (FileOutputStream fos = new FileOutputStream(entryFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = sevenZFile.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
}
}
}
}
出现报错。
打断点进行分析。显然这里分配了一个极大的内存,造成了内存不足。
回溯原因,nid==0x1的时候跳出,这里其实是反向寻找kHeader的Property ID,也就是反向找结束头的地方。pos==215,对应了D7处。
随后的0x05标识了这是一个FilesInfo,后面的UINT64标识长度,但是可以发现268435455对应的是0xFFFFFF而不是0xFFFFFFEF,这个原因是因为在7z中UINT和REAL UINT是不同的,这里由于E是0x1110,所以根据以下算法,其int之为0xFFFFFFF,正好对上十进制结果268435455。
3.1.6 漏洞复现
解压文件,出现OutOfMemoryError。
3.1.7 漏洞修复
1.升级Apache Commons Compress至已修复版本
升级Apache Commons Compress > 1.20
由于1.6-1.20版本出现了许多漏洞,不建议只针对7z文件进行过滤,而是选择将组件升级到漏洞不存在的版本。
文章评论