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

如何修复Gitlab SAST检测到的Java文件对象路径遍历漏洞?

修复Gitlab SAST检测到的Java路径遍历漏洞

问题场景

通过输入字符串创建File对象并写入文件,已用FilenameUtils.normalize()处理filePath修复了部分漏洞,但FileOutputStream fos = new FileOutputStream( file , false );仍被检测出路径遍历问题,尝试getCanonicalPath()未解决。

原代码

private BufferedWriter createFile( String filePath, String fileName )
{       
    try {
        File dir = new File( FilenameUtils.normalize(filePath) );

        if ( ! dir.exists() ) {
            if (! dir.mkdirs() ) {
                log("** WARNING: The file " + fileName + " cannot be created because the path " + filePath  + " could not be created **\n");
                return null;
            }
        }
    
        File file = new File(dir.getPath() + File.separatorChar + fileName);
        if ( file.exists() )
            file.delete();

        FileOutputStream fos = new FileOutputStream( file , false );
        ps = new PrintStream(fos);
        
        return new BufferedWriter(new FileWriter(file));
    }
    catch (Exception e) {
        log("** Warning: could not create file : " + filePath + File.separatorChar + fileName + " **\n");
        e.printStackTrace();
        return null;
    }
}

漏洞根源

当前漏洞的核心是**fileName参数未做任何校验和规范化**:即使filePath被处理,若fileName包含../、..\或跨系统的路径分隔符,拼接后仍能跳出目标目录,实现路径遍历。此外,字符串拼接路径的方式容易引入分隔符问题,且未验证最终文件是否确实落在允许的目录范围内。

修复方案

1. 规范化并校验fileName

使用FilenameUtils.getName()提取纯文件名(自动去除路径部分),确保fileName只是单纯的文件名而非路径,从根源上阻断遍历可能。

2. 安全拼接路径

用File类的构造方法new File(dir, fileName)代替字符串拼接,避免手动处理分隔符的错误。

3. 验证文件路径范围

通过getCanonicalPath()获取目录和文件的规范绝对路径,检查文件路径是否以目录路径开头,确保文件不会被创建到目标目录之外。

4. 清理冗余资源

原代码中创建的FileOutputStream和PrintStream未被使用,且ps作为类成员容易引发资源泄漏,直接删除这部分代码。

修改后的完整代码

private BufferedWriter createFile(String filePath, String fileName) {
    try {
        // 规范化目录路径并获取规范绝对路径
        String normalizedDirPath = FilenameUtils.normalize(filePath);
        File dir = new File(normalizedDirPath);
        String dirCanonicalPath = dir.getCanonicalPath();

        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                log("** WARNING: The file " + fileName + " cannot be created because the path " + filePath + " could not be created **\n");
                return null;
            }
        }

        // 提取纯文件名,过滤路径遍历字符
        String safeFileName = FilenameUtils.getName(fileName);
        // 安全拼接文件路径
        File file = new File(dir, safeFileName);
        // 获取文件的规范绝对路径
        String fileCanonicalPath = file.getCanonicalPath();

        // 验证文件是否严格在目标目录范围内
        if (!fileCanonicalPath.startsWith(dirCanonicalPath + File.separator)) {
            log("** WARNING: Invalid file name or path traversal detected for file: " + fileName + " **\n");
            return null;
        }

        if (file.exists()) {
            file.delete();
        }

        // 直接创建BufferedWriter,移除冗余资源
        return new BufferedWriter(new FileWriter(file));
    } catch (Exception e) {
        log("** Warning: could not create file : " + filePath + File.separatorChar + fileName + " **\n");
        e.printStackTrace();
        return null;
    }
}

关键修改说明

  • safeFileName = FilenameUtils.getName(fileName):自动剥离fileName中的路径部分(比如../secret.txt会被处理为secret.txt),彻底避免路径遍历。
  • 路径范围验证:通过getCanonicalPath()获取真实的文件系统路径,确保文件路径严格隶属于目标目录,防止任何绕过规范化的遍历手段。
  • 移除冗余资源:原代码中fos和ps未被使用,且ps作为类成员可能导致资源未关闭,直接移除后消除泄漏风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:35:23