《Java编码指南:编写安全可靠程序的75条建议》—— 指南5:防止任意文件上传

简介: Java应用程序,包括Web应用程序,在接受文件上传的同时,必须确保攻击者不能上传或者传输恶意文件。如果被限制的文件中包含了可以在目标系统上执行的代码,那么应用程序层的防御将会受到威胁。例如,如果一个应用程序允许了HTML文件的上传,那么也就相当于间接允许了恶意代码的执行——攻击者可以提交一个有效的HTML文件,如果该文件包含了跨站脚本(XSS)攻击的代码片段,在程序缺乏输出过滤的情况下这些攻击脚本将会被有效执行。

本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.5节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F.Sutherland(迪恩 F.萨瑟兰), David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

指南5:防止任意文件上传

Java应用程序,包括Web应用程序,在接受文件上传的同时,必须确保攻击者不能上传或者传输恶意文件。如果被限制的文件中包含了可以在目标系统上执行的代码,那么应用程序层的防御将会受到威胁。例如,如果一个应用程序允许了HTML文件的上传,那么也就相当于间接允许了恶意代码的执行——攻击者可以提交一个有效的HTML文件,如果该文件包含了跨站脚本(XSS)攻击的代码片段,在程序缺乏输出过滤的情况下这些攻击脚本将会被有效执行。出于这个原因,许多应用程序都对可上传文件的类型做了限制。

也有可能出现上传的文件具有危险的后缀这种情况,如.exe(可执行文件后缀)和.sh(可执行脚本后缀),这种情况会导致服务器端应用程序执行任意代码。如果一个上传文件的应用程序,只对HTTP报头中的Content-Type(内容类型)字段进行了限制,那么该程序就容易遭受到这种攻击。

一个典型的支持文件上传的Java Server Page(JSP)页面可能包含以下代码:

<s:form action="doupload" method="POST" 
  enctype="multipart/form-data">
 <s:file name="uploadFile" label="Choose File" size="40" />
 <s:submit value="Upload" name="submit" />
</s:form>```
许多Java企业级框架都提供了相应的配置设置,旨在防止任意文件被上传。遗憾的是,大多数企业级框架都无法提供足够的保护。为了弥补这个不足,需要检查元数据属性中的文件大小、内容类型和文件内容。

####违规代码示例
下面的违规代码示例展示了Struts 2应用程序中实现上传功能的XML代码,其中拦截器(interceptor)代码的职责是允许文件上传。


 
   10240
  
   text/plain,image/JPEG,text/html
  
 

负责文件上传的代码在UploadAction类中:

public class UploadAction extends ActionSupport {
 private File uploadedFile;
 // setter and getter for uploadedFile

 public String execute() {
  try {
   // File path and file name are hardcoded for illustration
   File fileToCreate = new File("filepath", "filename");
   // Copy temporary file content to this file
   FileUtils.copyFile(uploadedFile, fileToCreate);
   return "SUCCESS";
  } catch (Throwable e) {
   addActionError(e.getMessage());
   return "ERROR";
  }
 }
}`
参数maximumSize确保了指定的Action不会接收到一个非常大的文件。参数allowedTypes定义了可以被接受的文件类型。然而,这种方法不能完全确保上传的文件符合安全要求,因为拦截器检查可以被轻易地绕过。如果攻击者使用一个代理工具在网络传输过程中改变原始HTTP请求的内容类型,那么该框架将无法防止文件的上传。因此,攻击者可以上传一个恶意文件,如扩展名为.exe的可执行文件。

合规解决方案

只有当文件的内容类型严格匹配文件的实际内容时,文件才能成功上传。例如,一个具有image头信息的文件,只能包含一个图像,不能包含可执行代码。下面的这个合规解决方案,使用Apache Tika库[Apache 2013],通过现有的解析器库检测和提取文档中的元数据信息和结构化文本内容。在调用负责上传文件的execute()方法之前,必须先调用checkMetaData()方法。

public class UploadAction extends ActionSupport {
 private File uploadedFile;
 // setter and getter for uploadedFile

 public String execute() {
  try {
   // File path and file name are hardcoded for illustration
   File fileToCreate = new File("filepath", "filename");

   boolean textPlain = checkMetaData(uploadedFile, 
    "text/plain");
   boolean img = checkMetaData(uploadedFile, "image/JPEG");
   boolean textHtml = checkMetaData(uploadedFile, 
    "text/html");

   if (!textPlain || !img || !textHtml) {
    return "ERROR";
   }

   // Copy temporary file content to this file
   FileUtils.copyFile(uploadedFile, fileToCreate);
   return "SUCCESS";
  } catch (Throwable e) {

   addActionError(e.getMessage());
   return "ERROR";
  }
 }

 public static boolean checkMetaData(
  File f, String getContentType) {
  try (InputStream is = new FileInputStream(f)) {
   ContentHandler contenthandler = new BodyContentHandler();
   Metadata metadata = new Metadata();
   metadata.set(Metadata.RESOURCE_NAME_KEY, f.getName());
   Parser parser = new AutoDetectParser();
   try {
    parser.parse(is, contenthandler, 
         metadata, new ParseContext());
   } catch (SAXException | TikaException e) {
    // Handle error
    return false;
   }
   if (metadata.get(Metadata.CONTENT_TYPE).equalsIgnoreCase(
      getContentType)) {
    return true;
   } else {
    return false;
   }
  } catch (IOException e) {
   // Handle error
   return false;
  }
 }
}```
AutoDetectParser会基于需要解析的文件的内容类型,选择最佳的可用解析器。

###适用性
相关文章
|
11月前
|
Java
Java实现随机生成某个省某个市的身份证号?如何编码?
【10月更文挑战第18天】Java实现随机生成某个省某个市的身份证号?如何编码?
720 5
|
6月前
|
Java C语言
课时8:Java程序基本概念(标识符与关键字)
课时8介绍Java程序中的标识符与关键字。标识符由字母、数字、下划线和美元符号组成,不能以数字开头且不能使用Java保留字。建议使用有意义的命名,如student_name、age。关键字是特殊标记,如蓝色字体所示。未使用的关键字有goto、const;特殊单词null、true、false不算关键字。JDK1.4后新增assert,JDK1.5后新增enum。
101 4
|
6月前
|
Java 编译器
课时7:Java程序基本概念(注释)
课时7介绍了Java程序中的注释。编程语言有其语法和语义,注释有助于理解代码需求,防止断档。Java支持三类注释:单行(//)、多行(/* */)和文档注释(/** */)。注释不会被编译器编译。范例中展示了如何在代码中使用注释,并强调了注释对项目文档管理的重要性。
|
7月前
|
Java
java引入本地 MultipartFile 实现多部分文件上传
在Java中,`MultipartFile`通常用于处理通过HTML表单上传的文件。但在某些情况下,需要直接从本地文件系统获取文件并上传。本文介绍如何创建一个实现了`MultipartFile`接口的本地类`LocalMultipartFile`,将本地文件转换为`MultipartFile`对象,简化文件上传流程。此方法适用于批量上传等场景,避免了表单上传的复杂性。代码示例展示了如何实现和使用该类进行文件上传操作。作者:华科云商小彭。链接:[稀土掘金](https://juejin.cn/post/7377559533785530431)。
324 18
|
6月前
|
存储 Java 数据库连接
【YashanDB知识库】Java程序调用存储过程,在提取clob时报YAS-00004
【YashanDB知识库】Java程序调用存储过程,在提取clob时报YAS-00004
|
6月前
|
搜索推荐 Java Android开发
课时146:使用JDT开发Java程序
在 Eclipse 之中提供有 JDT环境可以实现java 程序的开发,下面就通过一些功能进行演示。 项目开发流程
237 0
|
8月前
|
传感器 安全 算法
消防救援支队消防员单兵装备智能养护舱电机驱动java版程序(二)
本文探讨消防救援中智能养护舱电机驱动的Java程序设计,作为系列文章第二部分。通过自动化和智能化手段,智能养护舱提升了装备维护效率与准确性。文章详细介绍了电机驱动模块的设计与实现,包括硬件选型、PID控制策略、安全保护机制及Java程序架构,确保电机精确控制、稳定性和安全性。未来将优化功能并引入智能算法和物联网技术,进一步提升装备维护智能化水平。
|
8月前
|
IDE Java 开发工具
消防救援支队消防员单兵装备智能养护舱点击驱动java版程序(一)
智能消防作战服架通过电机驱动系统提升消防员作业效率和安全性。本文介绍基于Java的电机驱动程序开发,涵盖硬件准备、软件环境搭建及驱动程序实现。重点包括串口通信配置、电机控制类设计与控制逻辑实现,确保电机高效稳定运行。通过正确配置通信协议和串口参数,并添加异常处理机制,保障系统的安全性和可靠性。
|
6月前
|
Java 开发工具
课时5:第一个Java程序
课时5介绍了编写第一个Java程序的步骤,包括创建Hello.java文件、编写“Hello World”代码、编译和运行程序。主要内容有:1) 新建并编辑Hello.java;2) 编译Java源文件生成.class文件;3) 通过命令行解释执行Java程序;4) 解释主方法的作用及信息输出操作。本课强调了类定义、文件命名规则和基本程序结构的重要性,并建议初学者使用记事本编写代码以熟悉基础语法。
|
10月前
|
SQL 安全 Java
Java 异常处理:筑牢程序稳定性的 “安全网”
本文深入探讨Java异常处理,涵盖异常的基础分类、处理机制及最佳实践。从`Error`与`Exception`的区分,到`try-catch-finally`和`throws`的运用,再到自定义异常的设计,全面解析如何有效管理程序中的异常情况,提升代码的健壮性和可维护性。通过实例代码,帮助开发者掌握异常处理技巧,确保程序稳定运行。
157 2

热门文章

最新文章