Java反序列化数据绕WAF之延时分块传输
字数 1040 2025-08-09 17:09:26
Java反序列化数据绕WAF之延时分块传输技术详解
0x01 技术背景
分块传输编码(Chunked Transfer Encoding)是一种HTTP协议的数据传输机制,允许服务器在不知道内容总长度的情况下开始传输数据。在安全领域,这项技术被用于绕过WAF(Web应用防火墙)的检测。
问题发现
chunked-coding-converter插件在0.2.1及之前版本不支持二进制数据分块- 传统分块传输技术已被多数WAF识别和防御
- 反序列化攻击中携带大量脏数据时,传统方法难以绕过WAF
0x02 延时分块技术原理
WAF处理分块传输的典型流程
- 检测到分块传输数据包,启动专门线程接收
- 持续接收客户端传来的分块数据,直到收到结束标志
0\r\n\r\n - 合并所有分块内容并进行安全检测
延时分块核心思想
- 在分块之间引入随机延时
- 目的是延长WAF线程等待时间,消耗WAF性能
- 迫使WAF在性能和检测之间做出权衡,可能放弃完整接收
关键约束条件
- 分块间隔必须小于后端中间件的post timeout时间
- Tomcat默认20秒
- WebLogic默认30秒
0x03 技术实现细节
增强WAF识别难度的策略
- 延时时间随机化:设置最小和最大延时范围
- 分块长度随机化:每块数据长度不固定
- 垃圾注释随机化(可选):添加随机长度和内容的注释
实现步骤
1. 请求头处理
headers.remove("Content-Length");
headers.put("Transfer-Encoding", "chunked");
2. 建立连接
Socket socket = socket.connect(new InetSocketAddress(host, port));
OutputStream osw = socket.getOutputStream();
3. 发送请求头
osw.write(reqHeader);
osw.flush();
4. 分块发送请求体
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reqBody);
byte[] buffer = new byte[Util.getRandom(minChunkedLen,maxChunkedLen)];
while (byteArrayInputStream.read(buffer) != -1){
// 发送分块长度
String chunkedLen = Util.decimalToHex(buffer.length) + "\r\n";
osw.write(chunkedLen.getBytes());
osw.flush();
// 发送分块内容
byte[] chunked = Transfer.joinByteArray(buffer, "\r\n".getBytes());
osw.write(chunked);
osw.flush();
// 随机延时
int sleeptime = Util.getRandom(minSleepTime,maxSleepTime);
Thread.sleep(sleeptime);
buffer = new byte[Util.getRandom(minChunkedLen,maxChunkedLen)];
}
5. 发送结束标志
osw.write("0\r\n\r\n".getBytes());
osw.flush();
实现优化
- 添加"sleep chunked sender"功能
- 显示每块发送的详细信息:
- 内容
- 长度
- 延时时间
- 发送状态
- 预估分块数量和延时范围
0x04 技术要点补充
- 协议支持:仅HTTP/1.1支持分块传输
- 适用范围:所有POST请求均可使用分块传输,不限于反序列化和文件上传
- 头部特性:
Transfer-Encoding: chunked大小写不敏感 - 实际案例:将数据分成218块,总延时1分46秒发送,成功绕过WAF
0x05 防御建议
- 在WAF中设置合理的分块接收超时时间
- 对异常延时的分块传输请求进行标记和限制
- 在应用层实现完整数据重组后的二次检查
- 监控异常的分块传输模式,特别是随机延时特征
总结
延时分块传输技术通过随机化分块长度和发送间隔,有效增加了WAF的检测难度。这种技术在特定环境下能够绕过依赖完整数据重组的安全检测机制,为渗透测试提供了新的思路。防御方需要从协议解析和异常行为检测两方面加强防护。