文件上传漏洞防范——文件类型检测

2024-07-30 156 0

当时需要开发一个功能,管理员可以上传一个包含不良词语的文本文件。系统利用这些词语实时检查用户提交的内容。上传的文件需要遵循特定的格式。

为了防止用户上传文本文件以外的文件,我们可以在前端进行操作。

<input type="file" accept="text/plain" />

这样,用户只需在文件选择窗口中选择一个文本文件即可。然而,为了确保系统安全,仅仅在界面上阻止用户是不够的。有必要在后台重新验证上传的文件,看看用户是否上传了文本文件。我们需要解决的问题是确定用户上传文件的实际类型。

开始

说明上述问题,我们将建立一个演示系统,前端使用 React.js,后端使用 Java/Spring Boot。

我们的界面非常简单,由一个输入[type=file]和一个上传所选文件的按钮组成。选择文件时,用户界面将显示浏览器确定的 MIME 类型。上传文件后,系统将返回后台确定的 MIME 类型。所有源代码都在这里。此外,还要准备一些文件,以测试系统判断是否正确。

准备 3 个扩展名正确的文件,然后复制这些文件并重命名:

real.png -> fake.txt
real.jpg -> fake.zip
real.svg -> fake.docx

后台文件类型确定

项目的后台系统使用 Spring Boot 以 Java 编写。还实现了一个控制器,用于接收用户的上传请求。

@Slf4j
@RestController
public class UploadController {
  @PostMapping(path = "/check-file-type", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
   public ResponseEntity < Response > checkFileType(@RequestPart MultipartFile file) {
     // to be implemented
   }
}

以及将结果返回给用户的响应

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Response {
   private int status;
   private String message;
   private String mimeType;
  public Response(String mimeType) {
     this.status = HttpStatus.OK.value();
     this.message = "Successful";
     this.mimeType = mimeType;
   }
}

使用用户代理定义的 MIME 类型

当从 input[type=file] 中选择文件时,文件类型已由浏览器(用户代理)根据 MIME 类型格式确定,然后通过 Content-Type 请求头传输到后端。因此,控制器参数中的 MultipartFile 类已经包含了文件类型的信息。

现在,您可以使用 getContentType() 根据 MIME 类型确定文件类型。

@PostMapping(path = "/check-file-type", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity < Response > checkFileType(@RequestPart MultipartFile file) {
   String mimeType = file.getContentType();
   return ResponseEntity.ok(new Response(mimeType));
}

让我们测试一下上面准备的文件

就文件 real.png 而言,用户代理通过 .png 扩展名识别出了正确的 MIME 类型。但对于 fake.zip 文件,用户代理无法正确识别其文件类型为 JPG,而是通过 .zip 扩展名来确定。因此,当用户有意更改文件名和扩展名时,依赖客户端定义的 MIME 类型可能会有一些风险。每种文件类型都有不同的规范,存储方式也不同,因此如果要确定文件的确切类型,就需要读取该文件的内容。

MIME 类型和确定文件类型的一些方法 MIME 类型(多用途 Internet 邮件扩展)是一种定义文档、文件或字节集的性质和格式的标准。它在 IETF 的 RFC 6838中进行了定义和标准化。MIME 类型的结构包括类型和子类型:

类型/子类型 示例:text/plain、application/zip、...

详细说明

类型是数据类型所属的一般类别,如视频或文本。 子类型决定所分类的确切数据类型。例如对于文本类型,我们可以有 plain(纯文本)、html(HTML 源代码)或 calendar(iCalendar .ics 格式)等子类型。一般来说,MIME 类型是分配给文件类型的名称,用于确定传输数据的内容类型,以及基于该类型的应用程序的相应行为。根据 MIME 类型,我们可以确定文件类型,那么如何从一个文件中识别其 MIME 类型呢?要确定 MIME 类型,我们需要读取其内容。每种文件类型都会有不同的存储方式,比如 ZIP 文件的文件规范就像这里一样。但仍有一些共同特征可用于识别。 文件签名是存储在文件开头的模式字节(也称为神奇数字或神奇字节),用于识别文件的内容和格式。下表列出了一些常用格式的文件签名(在此查看一些文件签名)。

除了使用文件签名外,有时还需要读取文件内容来找到确切的文件类型。例如,SVG 格式本质上是 XML。因此,要确定它,除了需要读取魔法数字来确定 XML 格式外,还需要读取里面更多的内容,才能正确确定 SVG 格式。

其他一些格式,如 Apple iWork,实际上是 Zip 文件中 XML 文件的集合。此时,Zip 文件负责制作包含 XML 文件的容器。由于需要解压其中的内容,文件类型识别变得更加困难。

使用 Apache Tika

确定 MIME 类型 在 Java 系统中,可以使用 Apache Tika 提取信息并确定文件数据的确切格式。Apache Tika 可根据以下几个标准确定文件的数据格式:

魔数(Magic number)
文件名扩展名(File name extension):部分基于文件扩展名
从互联网下载文件的元数据(Metadata)
定义容器及其内容(container)

要在 Maven 项目中使用 Tika,可以在 pom.xml 中添加依赖关系:

<dependency>
     <groupId>org.apache.tik

4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

电力企业 | 安全建设框架
HTB-Infiltrator:一文带你走进域渗透
JAVA安全 | Classloader:理解与利用一篇就够了
多角度揭秘威胁行为组织CryptoCore复杂的加密货币欺诈活动
网络空间的“边水往事”?针对华语黑产及用户进行攻击的 APT-K-UN3 活动分析
伪装“黑神话悟空修改器”传播木马的活动分析

发布评论