Java JDBC导致的反序列化攻击原理解析

作者:Welk1n 时间:2023-09-24 15:38:42 

这篇文章主要介绍了Java JDBC导致的反序列化攻击原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

背景

上周BlackHat Europe 2019的议题《New Exploit Technique In Java Deserialization Attack》中提到了一个通过注入JDBC URL实现反序列化攻击的场景,简单分析一下。

分析

首先,当java应用使用MySQL Connector/J(官方的JDBC驱动,本文基于其8.0+版本)连接mysql时,JDBC URL的格式如下:protocol//[hosts]/[database]?properties,具体可看mysql官方文档,示例:jdbc:mysql://localhost:3306/test?useSSL=true

其中,protocol、host、database都比较好理解,URL中的properties可以设定MySQL Connector/J连接mysql服务器的具体方式,关于properties的官方文档地址,其中和本文相关的连接属性有两个,分别是autoDeserialize和queryInterceptors,前者是设定MySQL Connector/J是否反序列化BLOB类型的数据,后者是 * ,在查询执行时触发,由com.mysql.cj.protocol.a.NativeProtocol#sendQueryPacket方法源码可知,会在执行查询语句前后分别调用 * 的preProcess和postProcess方法。

接下来定位下反序列化的触发点,在mysql-connector-java组件下全局搜索关键字“.readObject()”,定位到com.mysql.cj.jdbc.result.ResultSetImpl类中的getObject(int columnIndex)方法,部分核心代码如下:


public Object getObject(int columnIndex) throws SQLException {
……
case BLOB:
byte[] data = getBytes(columnIndex);
if (this.connection.getPropertySet().getBooleanProperty(PropertyDefinitions.PNAME_autoDeserialize).getValue()) {
  Object obj = data;
  // Serialized object?
  try {
   ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
   ObjectInputStream objIn = new ObjectInputStream(bytesIn);
   obj = objIn.readObject();
  }
}
}

变量data即为mysql返回结果集,当JDBC URL中设定属性autoDeserialize为true时,会对类型为bit、binary以及blob的数据进行反序列化,如何触发getObject(int columnIndex)方法的调用呢?议题中给出的调用链如下:


> com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#preProcess/postProcess
> com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor#populateMapWithSessionStatusValues
> com.mysql.cj.jdbc.util.ResultSetUtil#resultSetToMap
> com.mysql.cj.jdbc.result.ResultSetImpl#getObject

ServerStatusDiffInterceptor即为此前提到过的 * ,在JDBC URL中设定属性queryInterceptors为ServerStatusDiffInterceptor时,执行查询语句会调用 * 的preProcess和postProcess方法,进而通过上述调用链最终调用getObject(int columnIndex)方法。

实际利用还有一个问题,最终调用getObject方法的对象是数据库返回的结果集,由populateMapWithSessionStatusValues方法可知:


try {
 toPopulate.clear();

stmt = this.connection.createStatement();
 rs = stmt.executeQuery("SHOW SESSION STATUS");
 ResultSetUtil.resultSetToMap(toPopulate, rs);
}

这个结果集是执行SQL语句“SHOW SESSION STATUS”后数据库返回的值,SQL语句“SHOW SESSION STATUS”返回当前数据库连接的状态值,实际是读取系统表INFORMATION_SCHEMA.SESSION_VARIABLES的值,也可能是PERFORMANCE_SCHEMA.SESSION_VARIABLES(Mysql版本差异导致)。但是mysql中INFORMATION_SCHEMA和PERFORMANCE_SCHEMA都是不允许被修改的,所以需要想办法操纵返回的数据。

利用条件

1.本质上还是Java原生的反序列化利用,所以需要环境中有可用的Gadget;

2.需要能伪造相关系统表的数据,将“SHOW SESSION STATUS”的执行结果设置为我们精心构造的反序列化数据,或者基于mysql连接协议,自定义返回数据,后面有时间的时候会写写这块儿。

3.可控的JDBC URL

来源:https://www.cnblogs.com/Welk1n/p/12056097.html

标签:Java,JDBC,反,序列,化
0
投稿

猜你喜欢

  • Java如何读取jar包中的resource资源文件

    2022-10-12 22:51:43
  • 通过FancyView提供 Android 酷炫的开屏动画实例代码

    2023-04-11 11:00:53
  • Spring security如何重写Filter实现json登录

    2023-09-15 13:33:31
  • android仿微信支付宝的支付密码输入框示例

    2023-09-27 22:11:47
  • C#判断当前程序是否通过管理员运行的方法

    2023-09-27 15:48:24
  • Android中Activity的四种启动模式和onNewIntent()

    2022-09-05 23:15:02
  • Spring AOP底层原理及代理模式

    2023-05-05 14:19:38
  • Android BottomSheet效果的两种实现方式

    2022-10-14 02:26:23
  • c#动态改变webservice的url访问地址

    2021-10-08 20:13:03
  • C# 实现颜色的梯度渐变案例

    2023-11-20 22:01:06
  • 结合线程池实现apache kafka消费者组的误区及解决方法

    2023-08-06 15:40:31
  • 浅谈Android中视图动画的属性与使用

    2023-04-15 22:41:12
  • C#中WebClient实现文件下载

    2022-10-11 18:04:57
  • Android Insets相关知识总结

    2023-04-24 09:08:23
  • Android ListView弹性效果的实现方法

    2023-08-07 19:06:40
  • Android studio保存logcat日志到本地的操作

    2022-04-03 23:31:03
  • C#实现AddRange为数组添加多个元素的方法

    2023-06-26 13:34:25
  • Android Flutter实现搜索的三种方式详解

    2023-07-10 18:00:49
  • Spring使用@Autowired为抽象父类注入依赖代码实例

    2023-02-01 09:30:35
  • 剑指Offer之Java算法习题精讲求和篇

    2022-04-07 14:05:36
  • asp之家 软件编程 m.aspxhome.com