type
Post
status
Published
date
slug
summary
tags
CTF
推荐
category
CTF-Knowledge
category (1)
icon
password
comment
一、JDBC简介
JDBC(Java DataBase Connectivity)是一种用于执行Sql语句的Java Api,即Java数据库连接,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,可以为多种关系数据库提供统一访问,提供了诸如查询和更新数据库中数据的方法,是Java访问数据库的标准规范。简单理解为链接数据库、对数据库操作都需要通过jdbc来实现。
Mysql JDBC 中包含一个危险的扩展参数: “autoDeserialize”。这个参数配置为 true 时,JDBC 客户端将会自动反序列化服务端返回的数据,造成RCE漏洞。
二、漏洞原理
若攻击者能控制JDBC连接设置项,则可以通过设置其配置指向恶意MySQL服务器触发ObjectInputStream.readObject(),构造反序列化利用链从而造成RCE。
通过JDBC连接MySQL服务端时,会有几句内置的查询语句需执行,其中两个查询的结果集在MySQL客户端进行处理时会被ObjectInputStream.readObject()进行反序列化处理。如果攻击者可以控制JDBC连接设置项,那么可以通过设置其配置指向恶意MySQL服务触发MySQL JDBC客户端的反序列化漏洞。
可被利用的两条查询语句:
- SHOW SESSION STATUS
- SHOW COLLATION
JDBC连接参数
- tatementInterceptors:连接参数是用于指定实现 com.mysql.jdbc.StatementInterceptor 接口的类的逗号分隔列表的参数。这些拦截器可用于通过在查询执行和结果返回之间插入自定义逻辑来影响查询执行的结果,这些拦截器将被添加到一个链中,第一个拦截器返回的结果将被传递到第二个拦截器,以此类推。在 8.0 中被queryInterceptors参数替代。
- queryInterceptors:一个逗号分割的Class列表(实现了com.mysql.cj.interceptors.QueryInterceptor接口的Class),在Query”之间”进行执行来影响结果。(效果上来看是在Query执行前后各插入一次操作)
- autoDeserialize:自动检测与反序列化存在BLOB字段中的对象。
- detectCustomCollations:驱动程序是否应该检测服务器上安装的自定义字符集/排序规则,如果此选项设置为“true”,驱动程序会在每次建立连接时从服务器获取实际的字符集/排序规则。这可能会显着减慢连接初始化速度。
三、MySQL JDBC 反序列化链
detectCustomCollations链
- 5.1.19-5.1.28:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&user=yso_JRE8u20_calc
- 5.1.29-5.1.48:jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc
- 5.1.49:不可用
- 6.0.2-6.0.6:jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc
- 8.x.x :不可用
ServerStatusDiffInterceptor链
- 5.1.0-5.1.10:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc 连接后需执行查询
- 5.1.11-5.x.xx:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.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 (包名中添加cj)
- 8.0.20以下:jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
四、利用链分析
1.detectCustomCollations链:
连接数据库
调用DriverManager.getConnection(url);
java.sql.DriverManager#getConnection()方法
调用至此类getConnection()方法
com.mysql.jdbc.NonRegisteringDriver#connect()方法
com.mysql.jdbc.ConnectionImpl#getInstance()方法
com.mysql.jdbc.Util#handleNewInstance()方法
调用至com.mysql.jdbc.JDBC4Connection构造方法
调用至com.mysql.jdbc.ConnectionImpl构造方法
调用至com.mysql.jdbc.ConnectionImpl#createNewIO()方法
调用至com.mysql.jdbc.ConnectionImpl#connectWithRetries()方法
调用至com.mysql.jdbc.ConnectionImpl#initializePropsFromServer()方法调用至buildCollationMapping()
调用链如下

5.1.19以下
5.1.19以下未使用Util.resultSetToMap,此链不存在反序列化漏洞
com.mysql.jdbc.ConnectionImpl#buildCollationMapping()方法(mysql-connector-java 5.1.18)
5.1.19-5.1.28
5.1.19-5.1.28版本只判断版本是否大于4.1.0,若大于则可直接利用。
com.mysql.jdbc.ConnectionImpl#buildCollationMapping()方法(mysql-connector-java 5.1.28)
payload

5.1.29-5.1.40
com.mysql.jdbc.ConnectionImpl#buildCollationMapping()方法(mysql-connector-java 5.1.35)
com.mysql.jdbc.Util#resultSetToMap()方法(mysql-connector-java 5.1.35)
com.mysql.jdbc.ResultSetImpl#getObject()方法(mysql-connector-java 5.1.35)
payload

5.1.41-5.1.48
com.mysql.jdbc.ConnectionImpl#buildCollationMapping()方法((mysql-connector-java 5.1.41))
5.1.41版本后,不再使用com.mysql.jdbc.Util#resultSetToMap()方法获取”SHOW COLLATION”的结果,但又直接调用了results.getObject(3)
调用至com.mysql.jdbc.ResultSetImpl#getObject()方法(mysql-connector-java 5.1.41)
调用至com.mysql.jdbc.ResultSetImpl#getObjectDeserializingIfNeeded()方法(mysql-connector-java 5.1.41) 直接执行
payload
因为调用的是results.getObject(3),故需修改MySQL_Fake_Server代码,server.py 147行,将传入数据第三列改为JAVA序列化字符串。


5.1.49
com.mysql.jdbc.ConnectionImpl#buildCollationMapping()方法(mysql-connector-java 5.1.49)
5.1.49版本不再调用results.getObject(),此利用链失效
6.0.2-6.0.6
com.mysql.cj.jdbc.ConnectionImpl#buildCollationMapping()方法(mysql-connector-java 6.0.2)
调用com.mysql.cj.jdbc.util.ResultSetUtil.resultSetToMap()
调用getObject(),最后调用至readObject()
payload

8.x.x 以上
mysql-connector-java 8.0以上不再在com.mysql.cj.jdbc.ConnectionImpl中直接执行及获取”SHOW COLLATION”语句,调用链更改,不再调用getObject()方法,此链失效
com.mysql.cj.jdbc.ConnectionImpl#initializePropsFromServer()方法
com.mysql.cj.mysqla.MysqlaSession#buildCollationMapping()方法
2.ServerStatusDiffInterceptor链
ServerStatusDiffInterceptor是一个拦截器,在JDBC URL中设置属性queryInterceptors(8.0以下为statementInterceptors)为ServerStatusDiffInterceptor时,执行查询语句会调用拦截器的 preProcess 和 postProcess 方法,进而调用 getObject () 方法。
连接数据库:
- 作者:qetx
- 链接:http://qetx.top/article/87df9152-7a93-4af6-9914-c4d562dda540
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。








