当前位置:   article > 正文

应用安全系列之二十四:文件上传_输入验证:文件上传

输入验证:文件上传

        随着Web应用功能的不断丰富和需求的不断增加,文件上传已经成为非常重要的功能之一,例如:注册用户时,上传头像,几乎都成为标配了。 虽然文件上传已经成为非常重要的功能,但是,它也带来一定的风险。本文主要介绍文件上传的相关问题和预防措施。

        总体来说,文件上传的威胁主要来自四个方面:文件名称、文件类型、文件大小和文件内容。

文件名称:

        关于文件名称主要是可能文件名中含有一些比较危险的字符导致文件在被保存的时候,出现了意料之外的结果,例如,文件名称含有../或者..\,以及 ~等字符,这些字符都有特殊的意义,会导致文件被保存到预期之外的路径下。这种行为可能导致的问题就比较严重,因为上传的目标路径,一般都会设置为不可执行的,如果网站上显示的图片或者网页被覆盖,可能导致网站显示异常;如果一个可以执行的文件被存到上传目标路径之外其他路径,而且,这个路径又是可以执行文件的,就会带来灾难的后果。

        有些操作系统也有一些特殊的特性,也可能导致文件被覆盖。例如:Windows 8.3的功能,web.config就可以被短文件名web~1.con覆盖,“.htaccess”可以被“HTACCE~1”覆盖。如果web应用的配置文件被修改,攻击者可以控制应用的很多配置,导致应用的很多不安全的功能被打开,让攻击者更加容易地攻击系统。

        文件名带来的另外一个威胁就是,当文件名不合法时,如果系统处理不正确,可能导致系统内部信息泄露,例如:windows中含有 非法字符 |<>*?”,就会出错;在操作系统中,文件的名字和路径加在一起是有一定限制的,如果文件名字太长(>255)个字符,或者文件名+上传路径的长度>255,就会出问题。当出错时,如果处理不当就会导致信息泄露。有的网站处理不当会泄露非常重要的内部信息,如下:

 关于文件名的相关攻击的预防就是:做严格的输入验证,检测文件名中是否含有非法字符,检测文件名的长度是否超长。

文件类型:

        文件类型主要是上传文件的扩展名控制,如果扩展名没有做任何检查,可能会上传一些webshell,例如:jsp,php,asp,exe,bat,sh等可以执行的脚本或者文件,而这些脚本一旦可以通过某种途径出发执行,攻击者就可以执行任何命令,甚至控制整个服务器。即使不能触发执行,此文件如果可以在网站上分享给其他人,就可以引诱被攻击者访问此文件并发起攻击。

       针对文件类型的预防措施也比较简单:主要是使用一个允许的扩展名的白名单,只要不在这个白名单里的类型,一律拒绝。例如:一个上传csv文件的功能,就可以限制只能上传csv为扩展名的文件。在具体实施时,也需要注意,如果某个文件有多个点[.],例如:file.php.csv,一定要验证最后一个点之后的扩展名。

        当然文件名只是用于显示使用的,系统内部完全可以不再文件系统上使用上传者的文件名,可以使用随机数产生一个随机数作为文件系统的名字,再在数据库里,将文件的名字和这个随机数文件名的对应关系保存好,这样无论文件名字包含什么字符,都不会对文件系统有任何影响。

文件大小:

        如果对文件大小没有任何限制,可能导致的问题就是DOS攻击,当一个系统不限制上传文件的大小时,可能导致系统的空间被占用,再上传时,系统的IO资源和内存也被占用,攻击者可以利用这一点发起DOS攻击。

        关于文件大小攻击的预防措施:就是做严格的输入验证,任何一个上传的地方,根据需求,设置一个可以接受的文件的大小限制。例如:一个上传头像的功能,上传文件>100M就不正常。

文件内容:

        HTTP协议的content-type可以用于定义传输内容的类型,但是,这个类型是可以随意篡改的,不太可信。所以,服务器端最好有相关的检测功能,可以参考Apache Tika来检测文件的类型是否符合需求,关于各种文件的类型的特征可以参考:https://en.wikipedia.org/wiki/List_of_file_signaturesicon-default.png?t=N7T8https://en.wikipedia.org/wiki/List_of_file_signatures;病毒检测功能,有些杀病毒的厂商也提供一些SDK或者API用于快速检测文件。对于一些需要解析的文件,例如:XML,需要在解析时,注意API的配置的正确,防止XXE和XML Bomb的攻击。

        当上传的文件是压缩文件时,就更需要小心。首先,解压缩之后的大小会比压缩文件大很多,注意文件大小的控制;其次,在解压缩时,需要注意压缩包里的文件名称【参考前面文件名称】可能包含异常的字符,例如:../【可以尝试使用MAC操作系统创建这种文件名】。在解压缩之后,可能会导致文件被解压到预料之外的路径。因此,在解压缩并且保存压缩包里的文件时,每一个文件名都需要严格验证,以防万一。关于如何在解压缩时验证文件名的安全,可以参考【IDS04-J. Safely extract files from ZipInputStream - SEI CERT Oracle Coding Standard for Java - Confluence

关于文件内容的类型检测,可以查阅:如何判断一个文件的类型_jimmyleeee的博客-CSDN博客Java如何判断一个上传文件的内容类型_jimmyleeee的博客-CSDN博客

 文件上传容易犯的错误

  • 只在客户端使用JavaScript验证上传的文件名和扩展名
  • 忽略针对文件大小的验证
  • 完全版依赖content-type判断文件的类型,有些语言提供某种类型的文件的专用的API,例如:PHP提供了getimagesize,如果上传的不是图片,这个API就获取不到信息,通过此API就可以判断是否上传的是图片;
  • 代码实现错误,没有根据最后一个.之后的扩展名判断文件的类型

 文件上传预防措施:

        文件上传漏洞危害非常大,需要谨慎小心预防,总体来说需要注意一下几个要点:

        1. 严格进行输入验证,包含文件名、文件大小和文件类型,特别是压缩文件;

        2. 注意上传路径的权限设置,最受最小权限原则,防止文件被执行;

        3. 加强文件检测,以防病毒被上传;

        4. 尽量使用白名单,而不是黑名单;

        5. 制定编码规范,统一错误处理,防止信息泄露;

        6. 使用API解析文件时,一定要注意API的安全设置项,防止解析文件时被攻击。

        7. 检测文件的类型是否是在允许的类型范围内【Java语言的文件类型检查可以参考:Determining File Types in Java - DZone Java】;

简单总结为如下表格:

检测部分说明
文件名是否含有非法字符,例如:.. ~ 等字符,导致路径跳转;长度是否超过限制
扩展名是否在允许的白名单范围
文件大小是否控制了文件的最大的size
文件类型文件类型是否在允许的列表中。

        最后,要记住的一句话是:一起输入皆为恶。无论是从外部输入,还是内部其他模块的输入,都需要严格验证输入。养成一个良好的思维与习惯,才是构建安全产品的关键。

参考:

Unrestricted File Upload | OWASP Foundation

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/787003
推荐阅读
相关标签
  

闽ICP备14008679号