ToB企服应用市场:ToB评测及商务社交产业平台

标题: 文件上传漏洞防范-文件类型检测 [打印本页]

作者: 用多少眼泪才能让你相信    时间: 2024-5-18 23:35
标题: 文件上传漏洞防范-文件类型检测
文件上传漏洞防范-文件类型检测<br><br>      当时需要开辟一个功能,管理员可以上传一个包含不良词语的文本文件。系统使用这些词语及时检查用户提交的内容。上传的文件需要遵循特定的格式。<br>为了防止用户上传文本文件以外的文件,我们可以在前端进行操作。<br>
<br>
     这样,用户只需在文件选择窗口中选择一个文本文件即可。然而,为了确保系统安全,仅仅在界面上阻止用户是不敷的。有必要在背景重新验证上传的文件,看看用户是否上传了文本文件。我们需要解决的问题是确定用户上传文件的实际类型。<br>开始<br>说明上述问题,我们将建立一个演示系统,前端使用 React.js,后端使用 Java/Spring Boot。<br>
<br>我们的界面非常简朴,由一个输入[type=file]和一个上传所选文件的按钮组成。选择文件时,用户界面将显示浏览器确定的 MIME 类型。上传文件后,系统将返回背景确定的 MIME 类型。所有源代码都在这里。别的,还要准备一些文件,以测试系统判断是否精确。<br>
<br>准备 3 个扩展名精确的文件,然后复制这些文件并重命名:<br>
real.png -> fake.txt <br>real.jpg -> fake.zip <br>real.svg -> fake.docx<br>
背景文件类型确定<br> 项目的背景系统使用 Spring Boot 以 Java 编写。还实现了一个控制器,用于吸收用户的上传哀求。<br>
@Slf4j<br>@RestController<br>public class UploadController {<br>  @PostMapping(path = "/check-file-type", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)<br>   public ResponseEntity < Response > checkFileType(@RequestPart MultipartFile file) {<br>     // to be implemented<br>   }<br>}<br>
以及将效果返回给用户的相应<br>
@Data<br>@NoArgsConstructor<br>@AllArgsConstructor<br>public class Response {<br>   private int status;<br>   private String message;<br>   private String mimeType;<br>  public Response(String mimeType) {<br>     this.status = HttpStatus.OK.value();<br>     this.message = "Successful";<br>     this.mimeType = mimeType;<br>   }<br>}<br>
使用用户代理定义的 MIME 类型 <br>当从 input[type=file] 中选择文件时,文件类型已由浏览器(用户代理)根据 MIME 类型格式确定,然后通过 Content-Type 哀求头传输到后端。因此,控制器参数中的 MultipartFile 类已经包含了文件类型的信息。<br>现在,您可以使用 getContentType() 根据 MIME 类型确定文件类型。<br>
@PostMapping(path = "/check-file-type", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)<br>public ResponseEntity < Response > checkFileType(@RequestPart MultipartFile file) {<br>   String mimeType = file.getContentType();<br>   return ResponseEntity.ok(new Response(mimeType));<br>}<br>
让我们测试一下上面准备的文件<br>
<br>     就文件 real.png 而言,用户代理通过 .png 扩展名辨认出了精确的 MIME 类型。但对于 fake.zip 文件,用户代理无法精确辨认其文件类型为 JPG,而是通过 .zip 扩展名来确定。因此,当用户有意更改文件名和扩展名时,依赖客户端定义的 MIME 类型大概会有一些风险。每种文件类型都有差别的规范,存储方式也差别,因此如果要确定文件的确切类型,就需要读取该文件的内容。<br>     MIME 类型和确定文件类型的一些方法 MIME 类型(多用途 Internet 邮件扩展)是一种定义文档、文件或字节集的性子和格式的尺度。它在 IETF 的 RFC 6838 中进行了定义和尺度化。MIME 类型的结构包括类型和子类型:<br>类型/子类型 示例:text/plain、application/zip、...<br>详细说明<br>      类型是数据类型所属的一般种别,如视频或文本。 子类型决定所分类的确切数据类型。例如对于文本类型,我们可以有 plain(纯文本)、html(HTML 源代码)或 calendar(iCalendar .ics 格式)等子类型。一般来说,MIME 类型是分配给文件类型的名称,用于确定传输数据的内容类型,以及基于该类型的应用步伐的相应行为。根据 MIME 类型,我们可以确定文件类型,那么如何从一个文件中辨认其 MIME 类型呢?要确定 MIME 类型,我们需要读取其内容。每种文件类型都会有差别的存储方式,比如 ZIP 文件的文件规范就像这里一样。但仍有一些共同特征可用于辨认。文件签名是存储在文件开头的模式字节(也称为神奇数字或神奇字节),用于辨认文件的内容和格式。下表列出了一些常用格式的文件签名(在此查看一些文件签名)。<br>
<br>除了使用文件签名外,有时还需要读取文件内容来找到确切的文件类型。例如,SVG 格式本质上是 XML。因此,要确定它,除了需要读取魔法数字来确定 XML 格式外,还需要读取里面更多的内容,才能精确确定 SVG 格式。<br>其他一些格式,如 Apple iWork,实际上是 Zip 文件中 XML 文件的集合。此时,Zip 文件负责制作包含 XML 文件的容器。由于需要解压其中的内容,文件类型辨认变得更加困难。使用 Apache Tika <br>     确定 MIME 类型 在 Java 系统中,可以使用 Apache Tika 提取信息并确定文件数据的确切格式。Apache Tika 可根据以下几个尺度确定文件的数据格式:<br>
魔数(Magic number)<br>文件名扩展名(File name extension):部门基于文件扩展名<br>从互联网下载文件的元数据(Metadata)<br>定义容器及其内容(container)<br>
要在 Maven 项目中使用 Tika,可以在 pom.xml 中添加依赖关系:<br>
<br>     org.apache.tika<br>     tika-core<br>     2.1.0<br><br>
因此,我们可以编写更多的函数,在文件上传到系统时确定文件的精确 MIME 类型。<br>
public class FileUtils {<br>   public static String getRealMimeType(MultipartFile file) {<br>     AutoDetectParser parser = new AutoDetectParser();<br>     Detector detector = parser.getDetector();<br>     try {<br>       Metadata metadata = new Metadata();<br>       TikaInputStream stream = TikaInputStream.get(file.getInputStream());<br>       MediaType mediaType = detector.detect(stream, metadata);<br>       return mediaType.toString();<br>     } catch (IOException e) {<br>       return MimeTypes.OCTET_STREAM;<br>     }<br>   }<br>}<br>
在背景再创建一个 API,并使用 Tika 来辨认 MIME 类型。<br>
@PostMapping(path = "/check-real-type", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)<br>public ResponseEntity < Response > checkRealType(@RequestPart MultipartFile file) {<br>   String mimeType = FileUtils.getRealMimeType(file);<br>   return ResponseEntity.ok(new Response(mimeType));<br>}<br>
然后,编辑用户界面,使用新创建的 API 将文件上传到背景,并用一些文件再次进行测试:<br>
<br>    在文件 real.png 中,Tika 辨认出了精确的 MIME 类型。在 fake.zip 文件中,尽管改名为 fake.zip,Tika 仍能精确辨认出文件的原始 MIME 类型为 image/jpeg。<br>Tika 支持的格式列表请点击此处<br><br><br>.netCore可以使用<br>https://www.nuget.org/packages/Mime-Detective<br>https://github.com/KevM/tikaondotnet<br>https://github.com/nissl-lab/toxy<br>Golang 可以使用<br>https://github.com/gabriel-vasile/mimetype<br>https://github.com/golang/go/blob/master/src/mime/type.go<br><br><br>小结      后端系统在吸收上传文件时应验证上传文件的类型。根据浏览器检测到的 MIME 类型来检查文件类型大概还不敷,因为在某些情况下,文件会被改成扩展名,以便对系统进行钓鱼。每种文件类型都有差别的结构。借助 Java 系统上的 Apache Tika,可以根据文件格式确定文件的确切类型。<br>总结安全干系关注点<br>用户和文件系统权限 <br>上传和下载限制 <br>只要在应用步伐属性文件中添加这两个属性,就能轻松实现这一目标:<br>
spring.servlet.multipart.max-file-size=10MB<br>spring.servlet.multipart.max-request-size=10MB<br>
扩展和类型验证 <br>
  1. <font size="3"># Using Apache Commons IO. </font>
复制代码
  1. <font size="3">Returns "pdf"</font>
复制代码
  1. <font size="3"><strong>import </strong>org.apache.commons.io.FilenameUtils;</font>
复制代码
  1. <font size="3">String extension = FilenameUtils.getExtension("test.pdf");</font>
复制代码
     3.设置精确的 Content-Type 类型,从文件中提取,而不是使用 Content-Type 标头。思量使用 Apache Tika。<br>
  1. <font size="3"><strong>import </strong>java.io.ByteArrayInputStream;<br><strong>import </strong>java.io.IOException;<br><strong>import </strong>org.apache.tika.config.TikaConfig;<br><strong>import </strong>org.apache.tika.detect.Detector;<br><strong>import </strong>org.apache.tika.io.TikaInputStream;<br><strong>import </strong>org.apache.tika.metadata.Metadata;<strong>public static </strong>String getContentType(<strong>byte</strong>[] fileBytes, String filenameWithExtension) <strong>throws </strong>IOException {<br>    TikaConfig config = TikaConfig.getDefaultConfig();<br>    Detector detector = config.getDetector();<br>    TikaInputStream stream = TikaInputStream.get(<strong>new </strong>ByteArrayInputStream(fileBytes));<br>    Metadata metadata = <strong>new </strong>Metadata();<br>    metadata.add(Metadata.RESOURCE_NAME_KEY, filenameWithExtension);<br>    <strong>return </strong>detector.detect(stream, metadata).toString();<br>}</font>
复制代码
  1. <font size="3"><strong>文件名消毒</strong> </font>
复制代码
  1. <font size="3"># Always has length 36 and is limited to 23 chars<strong>import </strong>java.util.UUID;<br><strong>public static </strong>String createUniqueFilename(String extension) {<br>    <strong>return </strong>UUID.<em>randomUUID</em>().toString() + <strong>"." </strong>extension;<br>}</font>
复制代码
  1. <font size="3"><strong>文件内容验证</strong> </font>
复制代码
文件存储位置 <br>
  1. <br>
复制代码
参考<br>今天先到这儿,盼望对云原生,技术领导力, 企业管理,系统架构设计与评估,团队管理, 项目管理, 产品管理,信息安全,团队建设 有参考作用 , 您大概感爱好的文章: <br>构建创业公司突击小团队<br>国际化情况下系统架构演化<br>微服务架构设计<br>视频直播平台的系统架构演化<br>微服务与Docker先容<br>Docker与CI持续集成/CD<br>互联网电商购物车架构演变案例<br>互联网业务场景下消息队列架构<br>互联网高效研发团队管理演进之一<br>消息系统架构设计演进<br>互联网电商搜索架构演化之一<br>企业信息化与软件工程的迷思<br>企业项目化管理先容<br>软件项目乐成之要素<br>人际沟透风格先容一<br>精益IT构造与分享式领导<br>学习型构造与企业<br>企业创新文化与品级观念<br>构造目标与个人目标<br>初创公司人才招聘与管理<br>人才公司情况与企业文化<br>企业文化、团队文化与知识共享<br>高效能的团队建设<br>项目管理沟通筹划<br>构建高效的研发与自动化运维 <br>某大型电商云平台实践 <br>互联网数据库架构设计思绪 <br>IT底子架构规划方案一(网络系统规划) <br>餐饮行业解决方案之客户分析流程 <br>餐饮行业解决方案之采购战略订定与实施流程 <br>餐饮行业解决方案之业务设计流程 <br>供应链需求调研CheckList <br>企业应用之性能及时度量系统演变 <br>如有想了解更多软件设计与架构, 系统IT,企业信息化, 团队管理 资讯,请关注我的微信订阅号:<br>
<br>作者:Petter Liu <br>出处:http://www.cnblogs.com/wintersun/ <br>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面显着位置给出原文连接,否则保留追究法律责任的权利。 该文章也同时发布在我的独立博客中-Petter Liu Blog。<br><br>免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4