我要你知道,在这个世界上,总有一个人是会永远等着你的。无论什么时候,无论在什么地方,总会有这么一个人。 ——《半生缘》
文件上传漏洞概述
- 文件上传漏洞通常是指,hacker上传了一个可执行脚本文件,这个脚本被服务器解析,hacker获得了执行服务端命令的能力(也就是通常所说的webshell的问题)
要想让攻击成功,需要以下几个条件:
- 上传的文件要被web容器解释执行,所以文件一定要上传到web容器所覆盖到的路径
- 用户能够从web上访问这个文件,如果不能访问,那么web容器也不会解析这个脚本,也就不能称之为漏洞
- 上传的文件如果被安全检出、格式化、图片压缩等功能改变了内容,则可能导致攻击不成功
绕过文件上传检查的功能
检查文件头
- 正常情况下,通过判断前10个字节,基本就能判断出一个文件的真实类型
- 浏览器的MINE Sniff功能是通过提取文件的前256个字节,来判断文件类型的
- 为了绕过这类功能,hacker一般会伪造一个合法的文件头,然后把真正的PHP文件放在它后面,但此时,仍然需要通过PHP来解释这个文件才能达到攻击效果
- 如果文件后缀是
.JPG
,那么Web Server很有可能把此文件当作静态文件来解析,不会调用PHP解释器,攻击条件就无法满足
检查文件后缀
- 很多应用都是通过上传文件的后缀,来判断其安全性的
- hacker可以修改上传的POST包,在
.php
后面加一个[\0].JPG
,就能骗过后缀检查,但对于服务器来说,这还是一个PHP文件,因为在PHP语言的常用字符串处理函数中,0x00([\0]的十六进制表示)被认为是终止符
web容器的文件解析问题
Apache的文件解析问题
在Apache1.x、2.x中,对文件名的解析,是从后往前的,直到遇到一个Apache认识的文件类型为止,例如phpshell.php.rar.rar.rar
,rar后缀是合法的,可以成功上传,但Apache不认识rar,它最终会认为这是一个php文件
IIS的文件解析问题
- IIS之于windows === Apache之于Unix
在IIS6中,曾经出现过这样2个漏洞:
- 如果文件名为
abc.asp;abc.jpg
,IIS6会把它解析为abc.asp
不会管分号后面的内容 - 有一次因为处理文件扩展名出错,导致
/*.asp/
目录下的所有文件都是作为asp文件解析的,无论你的后缀是什么
注意这2个IIS漏洞,是需要服务器的本地硬盘上确实存在这样的文件或文件夹,若只是通过web应用映射出来的URL,是无法触发的
URL映射
- url映射就是把URL转到另一个URL上面
- 这个功能一般是由WEB服务器来完成的
比如通过配置可以把http://www.123.com/index.php?id=1
映射为 http://www.123.com/index/1
,这样做可以方便搜索引擎进行搜索,而http://www.123.com/index/1
这个在服务器上其实是不存在的
WebDav中的PUT
- WebDav大大扩展了HTTP协议中的GET、POST、HEAD等功能,它所包含的PUT方法,允许用户上传文件到指定的路径下;它所包含的MOVE方法可以修改文件的名字
- 许多Web Server禁止此方法,或者对上传文件类型做了严格的限制
- 在IIS中,如果目录支持写的权利,同时开启了WebDav,就会支持PUT方法;如果勾选了“脚本资源访问”的复选框,就会支持MOVE方法
- 一般在攻击前,hacker会用OPTIONS方法探测一下服务器支持的方法类型,是否支持PUT和MOVE就一目了然了
PHP CGI 路径解析问题
在配置为fastcgi的php应用中曾出现过这样的漏洞:当访问http://www.xxx.com/path/test.jpg/notexist.php
时,若notsxit.php
不存在,那么test.jpg
会被当作php文件处理
原因:
在fastcgi方式下,php的配置文件中有一个默认开启的选项:
1 | cgi.fix_pathinfo = 1; |
在映射URL时,有2个环境变量很重要:一个是PATH_INFO
,另一个是SCRIPT_FILENAME
。
在上面的例子中:
1 | PATH_INFO = notexist.php; |
若上面的默认选项为1的话,因为notexist.php
是不存在的,所以SCRIPT_FILENAME
会向前递归地检查文件的合法性,此时发现/path/test.jpg
是合法的,然而此时PATH_INFO = notexist.php;
,所以test.jpg
会被当作php文件来处理
CGI与FastCGI
如果浏览器请求的是一个类似index.html
的静态页面,Web Server就直接找到对应的文件,然后返回给浏览器:
如果浏览器请求的是类似index.php
的动态页面,Web Server知道这是动态文件,所以会调用PHP解析器进行处理,然后返回数据给浏览器:
- CGI(Common Gateway Interface)全称是“通用网关接口”,是一种让客户端(web浏览器)与Web服务器(nginx等)程序进行通信(数据传输)的协议。用来规范web服务器传输到php解释器中的数据类型以及数据格式,也就是为了保证web server传递过来的数据是标准格式的。CGI为每一次请求增加一个进程,效率很低。
- FastCGI(Fast Common Gateway Interface)全称是“快速通用网关接口”是通用网关接口(CGI)的增强版本,由CGI发展改进而来,主要用来提高CGI程序性能。FastCGI致力于减少网页服务器与CGI程序之间互动的开销,从而使服务器可以同时处理更多的网页请求(提高并发访问)。
利用上传文件钓鱼
- 钓鱼网站在传播时,一般会利用XSS、服务器端302跳转,从正常的网站跳到钓鱼网站,例如
http://taobao.com/path/login.html?redirect_url=http://hacker.com/hacker.php?cm_cat=0
,这样在url地址栏就很长,会被一些细心的用户发现 - hacker如果上传一个图片(实际上为payload),在正常情况下,浏览器会把它当作图片处理,但在IE7以前,会“自作聪明”地把它作为html文件处理。
设计安全的文件上传功能
文件上传的目录设置为不可执行
- 只要web容器无法解析这个文件,攻击就无法成功。
- 很多大型网站在上传文件后,文件会放在独立的存储上,做静态文件处理。一方面,方便实用缓存加速,降低性能损耗;另一方面,杜绝了脚本执行的可能。
判断文件类型
- 可以结合使用MINE Type、后缀检查的方式检查
- 建议用白名单的方式检查,黑名单并不可靠
- 对于图片,可以使用压缩函数或者resize函数,破坏潜在的html代码
使用随机数改变文件名和文件路径
- payload要被hacker执行才有效果
- 如果应用使用随机数改变文件名和路径,hacker就无法访问执行
- 像
shell.php.rar.rar
这样的文件也会因为文件名被修改而攻击失败
本文链接: https://bano247.com/2021/11/06/文件上传漏洞/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!