定义
文件上传背景:“文件上传“功能已经成为现在Web应用的一种常见需求,它不但有助于提 高业务效率(例如:企业内部文件共享),更有助于优化用户的体验(例如:上传视频、图 片、头像等)。“文件上传“功能一方面带来良好的体验,另一方面也带来了 “安全问题”。
文件上传漏洞定义:文件上传漏洞是指由于服务器未对上传的文件进行严格的验证和过滤, 而导致的用户可以越过其本身权限向服务器上传可执行的恶意文件。这里上传的文件可以是 木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,“文件上传” 本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻 辑不够完善,则会导致严重的后果。
文件上传成因:
- 使用的开源编辑器存在上传漏洞
- 服务器配置不当
- 前端文件上传限制被绕过
- 过滤不严或被绕过
- 文件解析漏洞导致文件执行
- 文件路径截断
文件上传利用条件:
- 恶意文件可以成功上传
- 能够获取恶意文件上传后的路径
- 恶意文件能够访问
- 恶意文件内容可被执行或运行
文件上传危害
- 文件上传危害: 上传文件是web脚本语言时,服务器的web容器解释并执行了用户上传的脚本,导致代码执行。
- 上传文件是病毒或者木马时,主要用于诱骗用户或者管理员下载执行或者直接自励运行。
- 上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为(还有其他 通过类似方式控制策略文件的情况)
- 上传文件是钓鱼图片或为包含了脚本的图片,可以用于钓鱼或者通过文件包含漏洞包含并执行。
- 还有一些不常见的利用方法,比如将上传文件作为一个入口,溢出服务器的后台处理程序,如图 片解析模块等。
webshell概述
定义:以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以 将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后 门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这 些后门,得到一个命令执行环境,以达到控制网站服务器的目的,可以实现文件上传 下载、修改文件、操作数据库、执行任意命令等操作。这个后门文件就是所谓的 Webshell。
一句话木马:一句话木马是Webshell的一种,由于这类Webshell代码比较少,往往只有一 行代码,所以就被称为一句话木马。一句话木马虽然代码内容少且简单,但是结合Webshell 等后门管理工具,可以实现非常强大的功能。
<?php eval($_POST['cmd']);?>
文件上传漏洞
文件上传点:即所有可以向服务器上传文件的位置,常见的有头像上传、文本上传、视频发布、文 档编辑、商品管理等。
文件上传几乎都是POST方式提交参数,所以需要通过Burp抓包查看提交的请求包内容:
上传漏洞:如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致攻击者能够向某个可通过WEB访问的目录上传恶意文件,并被脚本解析器执行,这样就可以在远程服务器上执行恶意脚本,进而控制服务器。
绕过
前端JS校验
前端检验:当客户端选中要上传的文件点击上传的时候,如果没有向服务端发送 任何数据信息,就对本地文件进行检测是否是允许上传的文件类型,这种方式称 为客户端本地JavaScript检测。
判断方式:
- 断网:加载完网页后,断网,传入不符合要求的文件类型,是否依旧弹出提示文件类型不允许。
- 抓包:通过Burp等工具抓取上传文件的数据包,查看弹出文件类型不符合要求时,前后端是 否会有数据包交互。
绕过方法:
- 删除或者禁用前端JS(浏览器上编辑前端资源)
- 先将要上传文件类型改为满足条件的文件类型,满足前端校验,然后使用Burp Suite抓包篡改 上传的文件为需要的文件类型。
MIME类型检测
所谓MIME类型检测实际上就是客户端在上传文件到服务端的时候,服务端对客 户端上传的文件的Content-Type类型进行检测,如果是白名单所允许的,则可以正常上传,否则上传失败
文件内容检测
文件内容检测的概念:服务器一般会读取文件16进制头,使用getimagesize()函数检测图片文件内容, 或者使用exif_imagetype()函数获得图片文件的类型,判断文件是否是一个有效的图片文件,如果是, 则允许上传,否则的话,不允许上传。
检测内容:判断文件头是否合法。
绕过方法:
可通过添加合法文件头进行绕过,如GIF89a等。
➢ JPG : FF D8 FF E0 00 10 4A 46 49 46
➢ GIF : 47 49 46 38 39 61 (GIF89a)
➢ PNG: 89 50 4E 47
通过将木马文件和图片文件拼接成一个文件,形成图片:copy a.jpg/b + b.txt/a c.jpg
一般就是检查图片文件的大小,图片文件的尺寸之类的信息。伪造好文件幻数,在后 面添加一句话木马之后,再添加一些其他的内容,适当增大文件的大小。或者直接使用copy命令合成 的图片马
文件名检测
常见的文件名检测就是检测文件的后缀名,常见的方式有两种:黑名单限制(不允许上传哪些后缀文件)和白名单限制(只允许上传哪些后缀的文件)。
黑名单限制绕过:大小写绕过、文件别名绕过、特殊文件名绕过、.htaccess配 置重写等。
白名单限制绕过:解析漏洞绕过。
黑名单-大小写绕过
大小写绕过:当客户端选中要上传的文件点击上传的时候,程序会对上传文件的后缀名进行判断, 当操作系统为linux时,系统对大小写敏感,当程序使用黑名单限制用户上传的文件后缀且过滤语句 不严谨时,可以通过修改文件后缀名大小写的方法绕过上传验证。Windows系统对大小写不敏感, 一般无法通过大小写绕过。
绕过方法
burp抓包,修改大小写
黑名单-文件别名绕过
不同类型的网站,绕过黑名单的方式也不同,常见别名可分成下面几种:
PHP:php3、php5、php(后面加空格)、pHp(大小写混合)、pht、phtml、phps
ASP:aspx、cer、cdx、asa、aSp(大小写混合)
JSP:jspx、jspf、jSp(大小写混合) 前提条件:需要对于开启服务配置以识别别名。以apache下的php为例,需要添加 apache的配置:
AddType application/x-httpd-php .php .php3 .phtml
绕过方法
对于存在黑名单检测并且开启了别名配置的场景,可以通过一些脚本或者爆破 方式,尝试所有的常见的别名。Burp抓包后,修改filename为别名后缀即可
黑名单-特殊文件名绕过
服务端有时会对文件后缀进行限制,根据过滤的不同实现方式,可以采取一些特殊的文件名进行绕过。 常见的有如下四种,前三种都是基于windows文件名的特性,只有windows系统才能使用:
空格:1.php ,文件名最后跟一个空格,windows中文件后缀名末尾有空格会自动去掉。
点:1.php. ,只有windows下才能使用,1.php.会被当做1.php处理。
::$DATA文件流:1.php::$DATA,只有目标服务器操作系统为windows,才可以使用,会将::$DATA后面内容作为文件流处理,不会检测后面的内容,并保持::$DATA之前的内容为文件名。
双写后缀:1.pphphp,双写后缀被替换的php只能是p(php)hp,不能是ph(php)p,因为后一 个经过程序替换,会变成hpp后缀,无法识别。
黑名单-.htaccess配置重写
.htaccess文件:是Apache服务的分布式配置文件,该配置文件会覆盖Apache服务器的全局配置, 作用域是当前目录及其子目录。如果一个Web应用允许上传.htaccess 文件,那就意味着攻击者可以 更改目标域下的Apache的配置。
局限:首先目标必须使用的是Apache服务,并且Apache配置中开启允许.htaccess文件覆盖掉 Apache配置的属性。即mod_rewrite模块开启,允许重写属性配置成All:AllowOverride All。
分布式配置文件提供了针对目录改变配置的方法, 即在一个特定的文档目录中放置包含一个或多个 指令的文件, 以作用于此目录及其所有子目录。用户可以利用此文件定义解析文件的后缀,从而进行恶意利用。
绕过方法
例如:将.png文件当作PHP文件解析,将以下代码写入文件,并保存成.htaccess文件,放 到目标目录下,该目录下的所有png后缀都会被当做php解析运行。
- 追加配置:AddType application/x-httpd-php .png .jpg .gif
- 重写配置:SetHandler application/x-httpd-php .png .jpg .gif
操作步骤:
- 先上传.htaccess分布式配置文件到目标目录下,指定一些关键配置信息。
- 再上传其他恶意文件,通过重写配置后,能够直接解析执行。
白名单-解析漏洞
IIS解析漏洞
目录解析(IIS 6.0)
➢ 形式:xx.asp/xx.jpg
➢ 原理:检测文件名为jpg,但是IIS解析时默认从左到右,会把该文件按照.asp解析。
文件解析
➢ 形式:xx.asp;.jpg
➢ 原理:IIS默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件了。
Apache解析漏洞
Apache解析文件的规则是从右到左开始判断文件类型,如果后缀名为不可识别的 解析类型,就再往左读取。比如test.php.qwe.asd,“.qwe”和”.asd”这两种后缀是Apache不可 识别类型,直到第三个php,Apache就会把test.php.qwe.asd解析成php。
形式:test.php.et48r4t.h45hh
Apache其余配置问题导致漏洞:
如果在 Apache的conf里有这样一行配置AddHandler php5-script .php这时只要文件名里包 含.php即使文件名是 test2.php.jpg也会按照php来解析。
如果在Apache的conf里有这样一行配置AddType application/x-httpd-php .jpg即使扩展名是 jpg也会按照php来解析。
Nginx解析漏洞
Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置 文件中通过正则匹配设置SCRIPT_FILENAME。当访问www.xx.com/phpinfo.jpg/1.php这 个URL时,$fastcgi_script_name会被设置为“phpinfo.jpg/1.php”,然后构造成 SCRIPT_FILENAME传递给PHP CGI,但是PHP为什么会接受这样的参数,并将 phpinfo.jpg作为PHP文件解析呢?这就要说到fix_pathinfo这个选项了。 如果开启了该选 项,那么就会触发在PHP中的如下逻辑:
PHP会认为SCRIPT_FILENAME是phpinfo.jpg,而1.php是PATH_INFO,所以就会将 phpinfo.jpg按照PATH_INFO的类型,即PHP文件来解析了。
Nginx解析漏洞形式
www.xxxx.com/UploadFiles/image/1.jpg/1.php
www.xxxx.com/UploadFiles/image/1.jpg%00.php
www.xxxx.com/UploadFiles/image/1.jpg/%20\0.php
另外一种手法:上传一个名字为test.jpg的图片马,然后访问test.jpg/.php,在这个目录下就会自动生成一句话木马test.php。
00截断
目录路径检测:检测上传的路径是否合法,一旦程序员在写程序的时候对文件的 上传路径过滤不严格就很有可能产生00截断漏洞。
假设上传的文件名为:test.php.gif,通过抓包截断将test.php后面的 . 换成0x00, 即test.php0x00gif。操作系统在读取文件时,都是读取文件的16进制内容,而 0x00就是NULL、结束的意思。当操作系统读到0x00的时候,会认为文件已经结 束,从而将test.php0x00gif中的内容写入到test.php,从而达到攻击目的。
GET请求截断:%00与0x00截断的原理是一样的,只是GET请求时,服务器会自动 进行URL解码,会将%00解码成0x00。所以直接Burp抓包后修改文件名即可。
POST请求截断:但是当请求方式为POST方式时,没有解码的步骤,需要在提交 数据包时,就要保证文件名中编码已经为0x00。需要Burp抓包后,使用HEX模式 编辑请求包内的文件名,修改点(2e)为00。
但是这两种方式都需要系统有权限能够重新命名文件。即php版本小于5.3.4, php.ini中magic_quotes_gpc为OFF状态。
防护
防护思路:首先,上传的文件能够被Web容器解释执行。所以文件上传后所在的目录要是Web容 器所覆盖到的路径。 其次,用户能够从Web上访问这个文件。如果文件上传了,但用户无法通过 Web访问,或者无法得到Web容器解释这个脚本,也无法利用或对服务器造成危害。 最后,用户 上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也可能导致攻击不成功。防 范文件上传漏洞常见的几种方法:
- 文件上传的目录设置为不可执行:只要web容器无法解析该目录下面的文件,即使攻击者上传了 脚本文件,服务器本身也不会受到影响,这就需要开发者对于网站目录和文件的权限划分足够细 致。
- 判断文件类型:在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检 查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理, 可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
- 使用随机数改写文件名和文件路径:文件上传如果要执行代码,则需要用户能够访问到这个文件。 在某些环境中,用户能上传但不能访问。如果应用随机数改写文件名和路径,将极大地增加攻击的 成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。
- 单独设置文件服务器的域名:由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传 crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决。
限制上传文件大小:
- 配置web server允许的最大Post大小
- 限制上传文件的大小,防止由于内存、磁盘耗尽造成的拒绝服务。
- 可以在代码层面获取上传文件的大小,根据文件类型的不同进行进一步的过滤。
确保上传文件被访问正确返回:
- 将文件上传目录设置为静态资源目录,防止被解析为脚本执行。
- 使用代理页面隐藏文件真实路径。
- 使用上述方法时,确保Content-Type与实际文件类型一致。
- 如果文件不允许在页面展示,仅允许下载,请设置Content-disposition:attachment。