文件上传漏洞篇

文件上传是一种可直接对服务器getshell的漏洞利用方法,姿势多种多样,防不胜防。
但总体来说,除了在ctf中利用较广外,在实际中挺少利用成功的(有也不敢搞)。但我感觉文件上传真的是网络安全入门必备的几大技能之一,现在工具和方法已经非常成熟,利用难度低,攻击危害大。

漏洞简述

黑客利用网站的上传文件、图片、音乐等功能上传病毒木马,进而控制整台网站服务器。
上传的病毒木马即我们的webshell,一种交互式的网站程序。通常入侵者将此类文件上传后与正常网站文件混淆在一起,再通过网页访问或工具连接的方式来获得一个命令执行环境。入侵者通过这类webshell程序可以执行各种敏感操作,如上传/下载/修改文件,执行终端命令等。


一款“功能完善”的webshell,速称大马。

漏洞成因

文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。
这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
所以“文件上传”的根本原因在于服务器执行了用户上传的文件。防护举例:网盘,不管上传什么都当数据存放着,从不执行。
对于黑客来说,上传了webshell很可能只是整个攻击流程的前半部分。

利用条件

1.首先,上传的文件能够被web容器解释执行。所以文件上传后的目录要是web容器所覆盖到的路径。
2.其次,用户能从web访问这个文件。
3.最后,用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则可能导致攻击不成功。

这几个条件都是缺一不可的,当然,防御的话我们也可以从这里面下手,但防御起来要做的并不止这些,下面的篇幅会有介绍。
为了加深各位的印象,利用条件分析将在下面逐步讲解。

漏洞利用

整个攻击流程思路:寻找上传点 -> 突破限制上传webshell -> 尝试连接webshell -> getshell

寻找上传点

文件上传,顾名思义就是各种支持用户上传保存“文件”的地方。

在各大网站的个人中心,寻找个人管理页面,一般会支持上传头像文件(图片):

在论坛等地方,可能支持富文本编辑器,使各位发表的言论能带上图片或文档或html样式的高级文本编辑器能支持上传文件:

综合其它漏洞攻击方式,能进入网站后台管理页面,则大概率有文件上传点。同时,扫描网站的/upload目录或upload.php这样的页面以发现隐藏的上传页面。

突破限制上传

经验这东西都是要靠自己把握。
首先要找出网站过滤机制,可以通过:
1.不断Fuzz测试摸索
2.尝试获取源码、相同版本CMS源码、查看相关CVE等分析
3.上传“正常”文件,后续通过文件包含或服务器文件解析漏洞进行利用

由易入深开始打怪升级:
1.毫无过滤型
省略一千字…

2.仅客户端验证
基于客户端的验证都是不安全的。
当仅在客户端对上传文件做了安全检测而不在服务端做检测时,恶意用户可通过先上传修改了符合检测规则的恶意文件绕过客户端检测(浏览器端),再通过抓包工具截获发往服务端的数据流,并将规则修改回去再发送,使发往服务端的文件不受约束。或者干脆禁用浏览器js,使验证脚本不生效。

3.基于黑名单机制的过滤
防御原理:服务端对接收的文件类型做了限制,先把不允许上传的文件类型写入到黑名单列表。当用户上传文件时,若文件类型在黑名单列表中,则不允许通过。
但黑名单有他的局限性,即黑名单没列完整时,存在绕过的风险。如黑名单不允许上传.php后缀名的文件,但攻击者可以尝试上传.php2,.php3,.php5,.phtml等后缀的webshell。
漏洞分析:执行文件有多个扩展名,过滤有遗漏可使用不同的扩展名绕过限制。
仔细想想,每有一种病毒类型就要修改一次黑名单列表,万一有遗漏的或者有未知的未添加进黑名单里,后果依然不堪设想。举个简单点的例子,例如头像上传处只希望用户上传图片,不要上传乱七八糟的东西,那么我们就不要对那一堆乱七八糟的东西进行过滤了,就设置一个白名单列表,当用户上传的文件符合要求时才允许保存。
修复加固:完善黑名单列表/改用白名单机制。

4.基于白名单机制的过滤
防御原理:与黑名单机制相反,只需要把允许上传的文件类型写入到白名单列表。当用户上传文件时,若文件类型不在白名单列表中,则不允许通过。
好处:白名单是一种非常好的过滤机制,适用于接收文件类型单一的上传点,只用管理少部分即可极大限制黑客的活动范围。

但黑客可以通过欺骗服务器,将黑的说成白的,漏洞在于服务器是如何判断上传的文件类型的。如下图,真正的图片只有中间那一个。假设我们都把它们上传到服务器,那么第三个会被禁止上传,第一个虽然可以上传但由于.jpg这个后缀名,服务器将把它看成图片,所以上传成功了也不像之前那样能直接利用。

不过如果服务器用$_FILES['filename']['type']来获取文件类型,那么将正中攻击者下怀。该函数仅检查文件扩展名,而不是原始文件类型,而且数据完全由客户端提供。我们使用BurpSuite截获发往服务器的数据,修改数据包中的Content-Type以欺骗服务器(MIME验证)。

针对截取上传文件头进行判断的,可以适当伪造一下文件头。

针对对上传文件的后缀名做检测的,限制会更大。这种情况下我们只能上传符合条件的文件,如.jpg图片等,再根据服务器情况进行后续利用。(这里的.jpg不是一般的图片哦,是“图片马”)
修复加固:使用严谨的方法获取文件的正确类型。
示例代码:

<?php  
$allow_types = array('jpg' , 'png' , 'jpeg');
$file_type = end(explode('.' , $_FILES['filename']['name']));  # 以.切割文件名并提取最后一个,即后缀名
if(in_array($file_type , $allow_types)){                       # 判断文件后缀是否在白名单内
    echo "允许上传";
    # do something
}
else{
    die("不允许上传");
}

5.利用服务器文件解析漏洞
服务器运行环境等信息可以通过信息收集获得,但网上传得神乎其神的apache、nginx等各种解析漏洞,我复现了一些发现也没有那么有效,大部分都复现不了或出现各种状况,不过可以当作参考。

环境:IIS6.0
目录解析漏洞
漏洞原理:文件夹的名称中包含.asp等后缀,该目录下的文件将当作可执行文件解析。
示例:/xx.asp/xx.jpg xx.jpg可替换为任意文本文件(e.g. xx.txt),文本内容为后门代码

后缀解析漏洞
漏洞原理:;(分号)后面的内容不被解析
示例:/xx.asp;.jpg /xx.asp:.jpg(此处需抓包修改文件名再上传)

环境:IIS 7.0/IIS 7.5/Nginx <=0.8.37
漏洞描述:在默认Fast-CGI开启状况下,在一个文件路径(/xx.jpg)后面加上 /xx.php 会将 /xx.jpg/xx.php 解析为 php 文件
利用示例:
1.上传图片型webshell
2.找到该图片路径,如./upload/a.jpg
3.在该路径后添加./xx.php
4.使用蚁剑等工具连接(e.g. ./upload/a.jpg/xx.php)路径

环境:apache
未知后缀解析漏洞
漏洞示例:xx.php.x1.x2.x3 将被解析为xx.php
漏洞原理:Apache将从右至左开始判断后缀,若x3非可识别后缀,再判断x2,直到找到可识别后缀为止,然后将该可识别后缀进解析。
复现环境:apache
复现过程:我准备了几个文件,apache.html.xxxx.yy.zz,apache.php.xxxx.yy.zz,touxiang.jpg.xxxx.yy.zz(原本是什么文件自己猜)
首先.html和.jpg对应的文件都能正常解析,但.php的会出现500错误,不清楚是apache的问题还是PHP的问题。

HTTPD多后缀解析漏洞
漏洞原理:在有多个后缀的情况下,只要一个文件含有.php后缀的文件即将被识别成PHP文件,没必要是最后一个后缀。
漏洞示例:xx.php.jpg可以绕过白名单限制,且能被当作PHP文件执行。
复现环境:vulhub_docker

个人总结:大多数情况下不能执行PHP,改了很多配置也不行。然后参考资料的话,利用条件也是挺严苛的。即某些特定情况下才能被利用,有种打ctf专属漏洞的感觉,实际中不知道能不能遇到。

环境:nginx
其它条件:当php的配置文件中的选项cgi.fix_pathinfo = 1 (默认设置是1)
示例:当访问http://www.xxx.com/x.txt/x.php时,若x.php不存在,则PHP会递归向前解析,将x.txt当作php脚本来解析。
似乎是到目前为止唯一一个可以直接复现被利用的:

防御加固

回顾上面所说的利用条件,既然它们缺一不可,那么我们可以有针对性地防御。

首先需要对对用户上传的文件进行检测,前后端都做一遍效果会更好。使用黑名单机制的话务必要将所有不允许被执行的文件类型添加进去,在这方面使用白名单会比较方便省心,但在富文本编辑器或评论区这样的应用场景下,反而是黑名单机制更合适。

可将所有上传的文件都保存在类似upload这样的文件夹目录下,并将目录下的PHP文件权限设置为不可执行,也可以设置为不允许外网访问等。
apache示例,修改httpd.conf:

<Directory "/var/www/html/upload">      # 上传文件夹路径
<FilesMatch "\.(?i:php|php2|php3|php5|phtml)$">    # 不允许文件类型:PHP
Order Allow,Deny
Deny from all                           # 不允许被访问
</FilesMatch>
</Directory>

修改.htaccess文件,放在上传目录下:

RewriteEngine on RewriteCond % !^$
RewriteRule uploads/(.*).(php)$ – [F]
RewriteRule data/(.*).(php)$ – [F]
RewriteRule templets/(.*).(php)$ –[F]

nginx示例,修改nginx.conf:

location ~* ^/uploads/.*\.(php|php5)$
{
  deny all;
}

# 下面的不用管,上面的代码必须放在下面代码的前面
location ~ [^/]\.php(/|$)
{
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
}

修改apache或nginx配置,需要重启服务才能生效。
这样,即使攻击者上传了webshell也无法执行/访问,这样就不会被利用到了(但会存在文件包含等隐患,并不绝对安全)。

路径隐藏+改变文件结构
另外我们可以重命名用户上传的文件,通过随机的不可预测的命名规则(同时不公开保存目录及文件名),强制拼接指定后缀保存以改变文件类型等方法加大攻击者利用难度。

建议

对于使用网上cms建站,但又没有文件上传这个功能需求的,可将后端相应文件删除。因为即使将前端上传点隐藏/删除,攻击者只要获知了接收点即可伪造前端进行上传。
同时,过滤机制最好写死在代码内,我遇过一些cms将过滤名单写在了数据库(同时管理员可控),这样的话不排除攻击者会通过其它攻击方法(如SQL注入、弱口令登录)对过滤机制进行修改达到任意文件上传。

发表评论

电子邮件地址不会被公开。 必填项已用*标注