SV.DATA.FILE

可能会上传并自动处理潜在的有害文件

从 2023.2 版本开始,此检查器将支持 Jakarta EE。

漏洞与风险

带有某些扩展名的文件在某些环境下可以自动处理,如果未检查这些文件,则会允许攻击者注入恶意文件。

缓解与预防

实施以下做法:
  • 尽可能将上传的文件存储在 Web 根目录以外的位置。
  • 为上传的文件使用随机生成的文件名。
  • 确保在文件名中仅使用一个扩展名。如果允许上传 .htm 文件,则要考虑跨站点脚本的可能性。
  • 在区分大小写的系统上,确保执行文件扩展名的区分大小写评估。
  • 在上传文件之前检查 MIME 类型是否正确,但不要只依赖于 MIME 类型。
  • 尽可能确保只有带有允许的扩展名的文件才能从上传目录直接访问。例如,如果目录仅应包含图像,则限制对目录中任何 PHP/ASP 文件的访问。

漏洞代码示例 1

复制
import javax.servlet.http.*;
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
    String pLine = br.readLine();
    String filename = pLine.substring(pLine.lastIndexOf("\\"), pLine.lastIndexOf("\""));
    BufferedWriter bw = new BufferedWriter(new FileWriter(UPLOAD_DIRECTORY_STRING + filename, true));  // <- Defect detected here because of a new file been created with tainted name
   
    for (String line; (line=br.readLine())!=null; ) {
      if (line.indexOf(boundary) == -1) {
        bw.write(line);
        bw.newLine();
        bw.flush();
      }
   }
    bw.close();
  }

在此示例中,Klocwork 在第 6 行报告 SV.DATA.FILE 缺陷,指出“可能会上传并自动处理潜在的有害文件”。文件的内容和名称来自请求中,这会允许攻击者指定文件扩展名,因此可以自动处理文件。一些危险的文件扩展名包括 .exe、.py、.php。

修正代码示例 1

复制
import javax.servlet.http.*;
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
    String pLine = br.readLine();
    String filename = UUID.randomUUID().toString();
    BufferedWriter bw = new BufferedWriter(new FileWriter(UPLOAD_DIRECTORY_STRING + filename, true));
     
    for (String line; (line=br.readLine())!=null; ) {
        if (line.indexOf(boundary) == -1) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
    }
    bw.close();
 }

克服 SV.DATA.FILE 缺陷的一种简单方式是分配无扩展名的文件名。Klocwork 不再报告缺陷,因为文件名将设置为随机生成的 UUID。

漏洞代码示例 2

复制
import jakarta.servlet.http.*;
 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
   //get the file chosen by the user
   Part filePart = request.getPart("fileToUpload");
  
   //get the InputStream to store the file somewhere
   InputStream fileInputStream = filePart.getInputStream();
  
   //for example, you can copy the uploaded file to the server
   File fileToSave = new File("fileName.exe");
   Files.copy(fileInputStream, fileToSave.toPath(), StandardCopyOption.REPLACE_EXISTING); // Detect defect here because: filename is dangerous and content is from user request
 }

在此示例中,Klocwork 在第 11 行报告 SV.DATA.FILE 缺陷,指出“可能会上传并自动处理潜在的有害文件”。代码将来自请求的文件内容直接复制到可执行文件中。此请求可以自动处理或稍后故意运行,同时文件的扩展名可能会被修改或移除。

修正代码示例 2

复制
import jakarta.servlet.http.*;
 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
     //get   the file chosen by the user
     Part filePart = request.getPart("fileToUpload");
  
     //get the InputStream to store the file somewhere
     InputStream fileInputStream = filePart.getInputStream();
  
     //for example, you can copy the uploaded file to the server
     File fileToSave = new File(UUID.randomUUID().toString());
     Files.copy(fileInputStream, fileToSave.toPath(), StandardCopyOption.REPLACE_EXISTING);
 }

Klocwork 不再报告缺陷,因为最简单的解决方案是为文件提供一个生成的无扩展名的名称。

相关检查器

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 Java 分析。