Java反序列化数据绕WAF之延时分块传输

  • A+
所属分类:安全文章

本文首发于奇安信攻防社区

社区有奖征稿


· 基础稿费、额外激励、推荐作者、连载均有奖励,年度投稿top3还有神秘大奖!

· 将稿件提交至奇安信攻防社区(点击底部 阅读原文 ,加入社区)


点击链接了解征稿详情


0x01 背景

chunked-coding-converter在0.2.1以及之前版本是不支持对二进制数据进行分块的。这个问题实验室的darkr4y师傅今年3月份的时候就已经反馈了多次,由于懒癌在身一直没有更新。直到我自己遇到一个站点,反序列化带大量脏数据没有绕成功,于是又想起了分块传输。花了一点时间让插件支持了二进制数据,然而这样依然被拦截了!
Java反序列化数据绕WAF之延时分块传输

这也在意料之中,分块传输被公开已经有两年之久,很多WAF已经支持检测。那有没有办法让这个姿势重振往日雄风呢?

0x02 延时分块

通过测试,发现WAF一般是如下应对分块传输的。

  1. 发现数据包是分块传输,启动分块传输线程进行接收

  2. 分块传输线程不断接收客户端传来的分块,直到接收到0rnrn

  3. 将所有分块合并,并检测合并之后的内容。

当时和darkr4y师傅交流时,我们曾做过一个设想,在上一块传输完成后,sleep一段时间,再发送下一块。 目的是在2阶段延长WAF分块传输线程的等待时间,消耗WAF性能。这时有没有可能WAF为自身性能和为业务让步考虑,而放弃等待所有分块发送完呢?。这次正好遇到适合的环境来验证一下想法。
Java反序列化数据绕WAF之延时分块传输
当然了,我们块与块之间发送的间隔时间必须要小于后端中间件的post timeout,Tomcat默认是20s,weblogic是30s。

0x03 编码实现

为了加大WAF的识别难度,我们可以考虑以下3点。

  1. 延时时间随机化

  2. 分块长度随机化

  3. 垃圾注释内容与长度随机化[可选]

首先我们需要对原始request header进行处理。需要把Content-Length删除,分块传输不需要发送body长度,然后加上Transfer-Encoding: chunked头。

  1. headers.remove("Content-Length");

  2. headers.put("Transfer-Encoding","chunked");

其实调用HttpURLConnection.setChunkedStreamingMode(int chunkedLen)就可以实现分块发包。不过这个接口只能设置固定分块长度,而且无法直接控制分块时间间隔。于是我打算用socket来模拟发送http/https分块传输包,这样要灵活的多。以下是实现的简化代码。

  1. // 1.连接目标服务器

  2. Socket socket = socket.connect(new InetSocketAddress(host, port));

  3. OutputStream osw = socket.getOutputStream();

  4. // 2.发送request header

  5. osw.write(reqHeader);

  6. osw.flush();

  7. // 3.随机分块和随机延时发送request body

  8. ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reqBody);

  9. byte[] buffer = new byte[Util.getRandom(minChunkedLen,maxChunkedLen)];

  10. while (byteArrayInputStream.read(buffer) != -1){

  11.        // 3.1发送分块长度

  12.        final String chunkedLen = Util.decimalToHex(buffer.length) + "rn";

  13.        osw.write(chunkedLen.getBytes());

  14.        chunkeInfoEntity.setChunkedLen(buffer.length);

  15.        osw.flush();

  16.        // 3.2发送分块内容

  17.        byte[] chunked = Transfer.joinByteArray(buffer, "rn".getBytes());

  18.        osw.write(chunked);

  19.        osw.flush();

  20.        // 3.3延时

  21.        int sleeptime = Util.getRandom(minSleepTime,maxSleepTime);

  22.        Thread.sleep(sleeptime);

  23.        buffer = new byte[Util.getRandom(minChunkedLen,maxChunkedLen)]; // 获取新的buffer长度

  24. }

  25. // 4.发送完毕

  26. osw.write("0rnrn".getBytes());

  27. osw.flush();

  28. byte[] result = readFullHttpResponse(socket.getInputStream());

为了方便日后使用,我给chunked-coding-converter插件添加了sleep chunked sender,并添加很多细节功能,比如预估分块数量范围和延时范围,显示每一块发送的内容,长度,延时时间以及发送状态等等。

这里我直接使用最新版本,将被拦截的数据分成218块,共延时1分46秒发送,最终成功绕过WAF。
Java反序列化数据绕WAF之延时分块传输

0x04 一些零碎

最后列一点边边角角的东西,当餐后”甜点“,需要请自取。

  1. 只有HTTP/1.1支持分块传输

  2. POST包都支持分块,不局限仅仅于反序列化和上传包

  3. Transfer-Encoding: chunked大小写不敏感

END



【版权说明】本作品著作权归c0ny1所有,授权补天漏洞响应平台独家享有信息网络传播权,任何第三方未经授权,不得转载。



Java反序列化数据绕WAF之延时分块传输
c0ny1

漏洞在牛角尖上


敲黑板!转发≠学会,课代表给你们划重点了

复习列表





从某开源靶场详细学习SQL注入的过程


探秘之旅:为何打开书签会导致Chrome崩溃


HTTP 2.x 协议学习与实战


施耐德充电桩漏洞挖掘之旅


某攻防演练期间遇到的shuipfcms的RCE审计过程


某客户关系管理系统代码审计

Java反序列化数据绕WAF之延时分块传输


分享、点赞、在看,一键三连,yyds。
Java反序列化数据绕WAF之延时分块传输

点击阅读原文,加入社区,获取更多技术干货!

本文始发于微信公众号(补天平台):Java反序列化数据绕WAF之延时分块传输

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: