You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SonarQube提示归档文件处理存在安全风险:原因及修复方案

Zip文件列表读取的安全风险与修复

问题场景

我编写了如下Java方法:

public List<String> getZipFileList(String fullPath) throws IOException {
    logger.debug("====> ZipService: getZipFileList <====");
    List<String> fileList = new ArrayList<>();

    try (ZipFile zipFile = new ZipFile(fullPath)) {
        Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
        while (zipEntries.hasMoreElements()) {
            String fileName = ((ZipEntry) zipEntries.nextElement()).getName();
            fileList.add(fileName);
        }
    }

    return fileList;
}

在Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();这一行,SonarQube给出提示:

请确保在此处解压该归档文件是安全的。

请问该操作存在哪些安全风险,以及如何进行修复?


存在的安全风险

  • 路径遍历攻击:Zip条目的文件名可能包含../、绝对路径(如/etc/passwd)等恶意内容。如果后续基于这个列表执行解压或文件操作,会导致程序访问/修改预期目录外的敏感文件,破坏系统安全性。
  • Zip炸弹攻击:恶意Zip包可能包含海量极小文件,或者单个高度压缩的超大文件。即使当前方法仅读取文件名,若调用方后续基于此列表解压,会快速耗尽磁盘空间或内存,引发拒绝服务。
  • 符号链接风险:Zip包中可能包含符号链接条目,后续操作若跟随该链接,可能访问到系统受保护的文件或目录,破坏系统完整性。

修复方案

1. 校验文件名,拦截路径遍历

对每个ZipEntry的文件名进行合法性校验,拒绝包含路径跳出字符或绝对路径的条目:

public List<String> getZipFileList(String fullPath) throws IOException {
    logger.debug("====> ZipService: getZipFileList <====");
    List<String> fileList = new ArrayList<>();

    try (ZipFile zipFile = new ZipFile(fullPath)) {
        Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
        while (zipEntries.hasMoreElements()) {
            ZipEntry entry = zipEntries.nextElement();
            String fileName = entry.getName();
            
            // 拦截包含路径遍历字符、绝对路径的条目
            if (fileName.contains("..") 
                || fileName.startsWith("/") 
                || fileName.startsWith("\\")) {
                throw new IOException("Invalid malicious file entry: " + fileName);
            }
            
            fileList.add(fileName);
        }
    }

    return fileList;
}

2. 限制Zip包大小与条目数量

提前检查Zip文件大小,同时限制遍历的条目数量,防范Zip炸弹:

public List<String> getZipFileList(String fullPath) throws IOException {
    logger.debug("====> ZipService: getZipFileList <====");
    List<String> fileList = new ArrayList<>();
    File zipFile = new File(fullPath);
    
    // 限制Zip文件最大体积(示例:100MB)
    long maxAllowedSize = 100 * 1024 * 1024;
    if (zipFile.length() > maxAllowedSize) {
        throw new IOException("Zip file exceeds maximum allowed size");
    }

    try (ZipFile zf = new ZipFile(zipFile)) {
        Enumeration<? extends ZipEntry> zipEntries = zf.entries();
        int maxAllowedEntries = 1000; // 限制最大条目数
        int entryCount = 0;
        
        while (zipEntries.hasMoreElements()) {
            if (entryCount++ >= maxAllowedEntries) {
                throw new IOException("Too many entries in zip file, potential zip bomb");
            }
            
            ZipEntry entry = zipEntries.nextElement();
            String fileName = entry.getName();
            
            // 路径校验
            if (fileName.contains("..") 
                || fileName.startsWith("/") 
                || fileName.startsWith("\\")) {
                throw new IOException("Invalid malicious file entry: " + fileName);
            }
            
            // 拦截符号链接
            if (entry.isSymbolicLink()) {
                throw new IOException("Symbolic links are not permitted: " + fileName);
            }
            
            fileList.add(fileName);
        }
    }

    return fileList;
}

3. 过滤符号链接条目

直接拒绝符号链接类型的ZipEntry,避免后续操作跟随链接访问敏感资源。


内容的提问来源于stack exchange,提问作者Rolf Warnecke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:33:06