编写插件绕过WAF
一、在HTTP协议层面绕过WAF
原理
给服务器发送payload数据包,使得waf无法识别出payload,当apache,tomcat等web容器能正常解析其内容。如图一所示

实验环境
本机win10+xampp+某狗web应用防火墙最新版。为方便演示,存在sql注入的脚本中使用$_REQUEST["id"]来接收get,或者post提交的数据。waf配置为拦截url和post的and or 注入,如图二所示。

图二
发送get请求或利用hackbar插件发送post请求payload均被拦截,如图三。
图三

一· 利用pipline绕过[该方法经测试会被某狗拦截]
原理:
http协议是由tcp协议封装而来,当浏览器发起一个http请求时,浏览器先和服务器建立起连接tcp连接,然后发送http数据包(即我们用burpsuite截获的数据),其中包含了一个Connection字段,一般值为close,apache等容器根据这个字段决定是保持该tcp连接或是断开。当发送的内容太大,超过一个http包容量,需要分多次发送时,值会变成keep-alive,即本次发起的http请求所建立的tcp连接不断开,直到所发送内容结束Connection为close为止。
1. 关闭burp的Repeater的Content-Length自动更新,如图四所示,点击红圈的Repeater在下拉选项中取消update Content-Length选中。这一步至关重要!!!

2. burp截获post提交
,显示被waf拦截如图五所示。

3. 复制图五中的数据包黏贴到
后面如图六所示。
图六

4. 接着修改第一个数据包的数据部分,即将
修改为正常内容id=1,再将数据包的Content-Length的值设置为修改后的【id=1】的字符长度即4,最后将Connection字段值设为keep-alive。提交后如图七所示,会返回两个响应包,分别对应两个请求。

图七
注意:从结果看,第一个正常数据包返回了正确内容,第二个包含有效载荷的数据包被某狗waf拦截,说明两数据包都能到达服务器,在面对其他waf时有可能可以绕过。无论如何这仍是一种可学习了解的绕过方法,且可以和接下来的方法进行组合使用绕过。
二.利用分块编码传输绕过[该方法可绕某狗]
原理:
在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,post请求报文中的数据部分需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的,也不包括分块数据结尾的,且最后需要用0独占一行表示结束。
1. 开启上个实验中已关闭的content-length自动更新。给post请求包加入Transfer-Encoding: chunked后,将数据部分id=1 and 1=1进行分块编码(注意长度值必须为十六进制数),每一块里长度值独占一行,数据占一行如图八所示。
图八

2.将上面图八数据包的
改为
即将图八中所标的第4块的1改为2。如图九所示没有返回数据,payload生效。

图九
注意:分块编码传输需要将关键字and,or,select ,union等关键字拆开编码,不然仍然会被waf拦截。编码过程中长度需包括空格的长度。最后用0表示编码结束,并在0后空两行表示数据包结束,不然点击提交按钮后会看到一直处于waiting状态。
三.利用协议未覆盖进行绕过[同样会被某狗拦截]
原理:
HTTP头里的Content-Type一般有application/x-www-form-urlencoded,multipart/form-data,text/plain三种,其中multipart/form-data表示数据被编码为一条消息,页上的每个控件对应消息中的一个部分。所以,当waf没有规则匹配该协议传输的数据时可被绕过。
1.将头部Content-Type改为multipart/form-data; boundary=69 然后设置分割符内的Content-Disposition的name为要传参数的名称。数据部分则放在分割结束符上一行。
图十

由于是正常数据提交,所以从图十可知数据是能被apache容器正确解析的,尝试1 and 1=1也会被某狗waf拦截,但如果其他waf没有规则拦截这种方式提交的数据包,那么同样能绕过。
2.一般绕waf往往需要多种方式结合使用,如图十的示例中,只需将数据部分1 and 1=1用一个小数点"."当作连接符即1.and 1=1就可以起到绕过作用。当然,这只是用小数点当连接符所起的作用而已。如图十一所示。
图十一

四.分块编码+协议未覆盖组合绕过
1.在协议未覆盖的数据包中加入Transfer-Encoding: chunked ,然后将数据部分全部进行分块编码,如图十二所示(数据部分为1 and 1=1)。
图十二

注意:第2块,第3块,第7块,和第8块。
第2块中需要满足
这种形式,且长度值要将两个空行的长度计算在内(空行长度为2)。
第3块,即数据开始部分需满足
形式,且需将空行计算在内。
第7块即分割边界结束部分,需满足
形式,且计算空行长度在内。
第8块需满足
形式。如果不同时满足这四块的形式要求,payload将不会生效。
二、利用分块传输吊打所有WAF
技巧1 使用注释扰乱分块数据包
一些如Imperva、360等比较好的WAF已经对Transfer-Encoding的分块传输做了处理,可以把分块组合成完整的HTTP数据包,这时直接使用常规的分块传输方法尝试绕过的话,会被WAF直接识别并阻断。
我们可以在[RFC7230]中查看到有关分块传输的定义规范。
通过阅读规范发现分块传输可以在长度标识处加上分号“;”作为注释,如:
几乎所有可以识别Transfer-Encoding数据包的WAF,都没有处理分块数据包中长度标识处的注释,导致在分块数据包中加入注释的话,WAF就识别不出这个数据包了。
现在我们在使用了Imperva应用防火墙的网站测试常规的分块传输数据包:
返回的结果如下图所示。

可以看到我们的攻击payload “and 2=2”被Imperva的WAF拦截了。
这时我们将分块传输数据包加入注释符。
返回的结果如下图所示。

可以看到Imperva已经不拦截这个payload了。
技巧2 Bypass ModSecurity
众所周知ModSecurity是加载在中间件上的插件,所以不需要理会解析http数据包的问题,因为中间件已经帮它处理完了,那么无论使用常规的分块还是加了注释的分块数据包,ModSecurity都能直接获取到完整的http数据包然后匹配危险关键字,所以一些基于ModSecurity做的WAF产品难道就不受影响吗?
接下来我们在Apache+ModSecurity环境做测试。
sql.php 代码如下:
ModSecurity加载的规则拦截了请求包中的关键字“union”。
下面我们的请求和返回结果如下:
可以看到我们的“union”关键字被拦截了。
接下来我们传输一个畸形的分块数据包看看。
可以看到虽然apache报错了,但是因为apache容错很强,所以我们提交的参数依然传到了php,而我们的ModSecurity并没有处理400错误的数据包,最终绕过了ModSecurity。
接下来我们把ModSecurity的规则改为过滤返回数据中包含“root”的字符串,然后在sql.php脚本中加入打印“root”关键字的代码。
接着我们做如下测试:
因为 sql.php 脚本中返回了带有“root”的关键字,所以直接就被 ModSecurity 拦截了。这时我们改为发送畸形的分块数据包。
通过两个测试可以发现使用畸形的分块数据包可以直接绕过ModSecurity的检测。这个问题我们在2017年4月已提交给ModSecurity官方,但是因为种种问题目前依然未修复。
三、编写Burp分块传输插件绕WAF
0x01 功能设计
我们先来看看插件要实现的功能
在Burp Repeater套件上可对数据包进行快速chunked解码编码
自动化对Burp的Proxy,scanner,spider等套件的数据包进行编码
可设置分块长度,是否开启注释
0x02 编写代码
限于边幅,我只说明核心函数,并通过注释的方式解释代码的相关功能。
2.1 编码函数
这是我们的核心函数,对各个套件数据HTTP数据进行chunked编码
自动编码其他模块的数据包,我们可以通过实现Burp的IHttpListener,IProxyListener这两个接口,分别实现processHttpMessage(),processProxyMessage()这两个方法。
这里注意一个问题,Burp的所有模块的HTTP流量都会经过IHttpListener.processHttpMessage()这个方法,但是如果在这里处理数据包的话,Burp Proxy模块的数据包被修改之后,不会在Proxy套件UI界面显示修改后的流量,故Proxy模块流量处理单独使用IProxyListener.processProxyMessage()。
2.2 自动编码Proxy套件的流量
2.3 自动编码Proxy之外的套件(Intruder,scanner…)流量
完整的代码,已经上传github,地址如下:
http://github.com/c0ny1/chunked-coding-converter
0x03 效果演示
3.1 演示一:快速编码解码
在Burp repeater套件可以快速对请求内容进行chunked编码解码,来对WAF进行测试。

3.2 演示二:搭配sqlmap进行sql注入
sqlmap代理到Burp中,插件对Proxy套件的流量进行编码处理,来绕过waf。
搭配sqlmap绕waf

最后更新于
这有帮助吗?