绕waf之分块传输技术
分块传输理论知识
分块传输绕waf技术已经公开好几年,学习后作此总结。
HTTP/1.1中引入了分块传输编码的数据传输机制,允许客户端将请求体分块再传输,这得益于HTTP/1.1的长连接机制,分块传输的本意是为了提高效率,如将数据分块后再传输可以对每个数据块单独操作(如压缩解压缩、计算、整合等),而不需要等所有数据发送或接收完毕后再操作,大大节约时间空间成本。
分块传输的数据格式:
请求响应头不需要指定Content-Length,但是需要加入Transfer-Encoding: chunked来表明本数据包使用分块传输;
同时数据体分割为一系列数据块,每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括自己的结尾(rn),也不包括分块数据结尾的;
最后一个分块长度值必须为 0,对应的分块数据没有内容(两个空行),表示实体结束。
1 | Transfer-Encoding: chunked |
同时也可以在长度后加入注释内容,使用分号来表示注释开始
1 | Transfer-Encoding: chunked |
根据上述规则对数据进行分块传输,wireshark抓包看到http请求中的分块传输数据,长度与Burp中编码后的一致
对data做16进制转字符也能得到原始数据
分块传输实践
分块传输过安全狗
这里用的安全狗(Apache服务器版)V4.0.18089进行测试,需要配置打开SQL注入的POST拦截
直接注入被拦截:
对数据进行分块传输,不再拦截
查当前用户:
1 | id=2+and+extractvalue(1,concat(0x7e,(select+user()),0x7e))--+&submit=%E6%9F%A5%E8%AF%A2 |
拦截
分块传输,不拦截
当然也可以加入注释,即在每一个数据块大小后加入;注释字符
,用来绕过检测分块传输的waf,不过早在几年前也已经被过滤了
SQLMap联动分块传输插件
需要用到BurpSuite分块传输插件chunked-coding-converter,将SQLMap的流量代理到BurpSuite,BurpSuite中chunked-coding-converter config设置为Proxy自动分块
此时只要是通过代理走BurpSuite的流量都会被分块传输
1 | python .\sqlmap.py -r E:\Desktop\req.txt --batch --proxy http://127.0.0.1:8080 --dbs |
可以在Burp Logger中看到大量从SQLMap中过来的数据包,被插件进行分块传输编码,绕过waf注入
延时分块传输
在普通分块传输、带注释污染数据的分块传输均已经被主流waf拼接数据后进行防护拦截,又出现了绕过方法,即延时分块。
延时分块绕过的原理:
- 在原有分块传输的基础上每个分块加入延时,用以增加安全设备的等待时间,当等待时间超过安全设备的资源设定时间时,出于性能和业务的考量,安全设备会提前终止数据的接收拼接,即可实现脏数据的插入。
延时分块的注意点:
- 块与块之间发送的时延必须要小于后端中间件的timeout,Tomcat默认是20s,WebLogic是30s。
延时分块的实际利用:
- 同样可以使用BurpSuite分块传输插件chunked-coding-converter,c0ny1表哥在之前工具的基础上已经加入了延时功能,可设置分块长度以及每个分块的延时时间,并且会显示预计的分块数量和总耗时,配置好即可start进行延时注入
所有分块发送完毕后在response处查看结果。
个人疑点之分块传输深度探究
看完分块传输技术以及分块传输绕过waf的文章,当然不仅仅指的是本文,不知道你是否有以下疑惑:
- 客户端发送一个分块编码的http请求,为什么服务端就会分块接收?
- 整个分块的数据请求还是同一个http包发送接收的,为什么能够边发送边接收、边计算、边整合?
- 底层究竟是如何分块发送、接收的?
我在网上查了一些文章,但始终没有查到这部分内容,大都直接讲分块传输的几大好处如边传输边压缩、边传输边计算等,因此无法彻底理解分块传输的原理、过程、效果,索性抓包探究一下。
这里使用Wiresshark抓包,动图演示一下分块传输的数据包过程,为了更直观此处使用的延时分块
可以看到,每进行一次分块数据传输,就会发送几条对应的TCP请求响应包,看似是POST包,其实是传输层TCP层的数据包,只是Wireshark为了方便查看这样展示的,追踪TCP流后就会显示正常。
对分块传输的数据包分析如下图:
第一步:点击发送以后,首先进行TCP的三次握手,随即用2个TCP包分别发送http请求的首行(请求行)和请求头+第一个数据块。
第二步:用2个TCP请求实现一个数据块的传输,第一个TCP发送数据块大小,第二个TCP发送数据块内容。
原本的TCP MTU为1460,但是可以看到由于进行分块编码传输,所以每个包都没发满传输单元
第三步:当所有分块数据都用步骤二发送完毕时,再发送一个数据结束标识符,即0\r\n\r\n,Wireshark进行了可视化组装,所以要在HTTP请求中看。
这样一次分块传输的数据就发送完成了。
这样看来Wireshark中显示的HTTP数据包其实是自己组装起来展示的,因为它监听的是网卡数据,而发包时数据流向是自顶向下,即应用层->传输层->网络层->数据链路层->物理层,Wireshark接收到所有数据后进行组装,来做可视化展示。
经过以上实操学习,总结起来,个人的疑虑无非用一句话解释:分块传输发生在TCP传输层,HTTP应用层只负责提供格式和组装格式。因此在BurpSuite上看似点了一次Send,发了一个数据包,其实传输层才是对接收到的应用层数据进行分块处理的,因为TCP协议负责数据的分组和组装。
正因为如此,分块传输才能绕waf,当然现在来看也只能是绕过包过滤类型的防火墙,因为这种防火墙检测的是TCP、UDP、ICMP等网络层、传输层的数据包内容,不像应用代理防护墙,检测的是应用层的数据包内容。