深入分析 ImmutableSetMultimap 反序列化利用链
字数 1889 2025-12-26 12:10:39

ImmutableSetMultimap 反序列化利用链深入分析

概述

本文深入分析 Guava 库中 ImmutableSetMultimap 类的反序列化利用链。该漏洞利用 Guava 不可变集合在反序列化过程中的空值检查机制,结合特定对象触发恶意代码执行。

漏洞背景

核心组件

  • ImmutableSetMultimap: Guava 库中的不可变多重映射集合
  • JSONArray: Jackson 库中的 JSON 数组实现
  • DruidXADataSource: 阿里 Druid 连接池的 XA 数据源实现

关键技术点

  • Jackson 的 JSONArray.toString() 方法会自动调用类的 getter 方法
  • Guava 的不可变集合在反序列化时具有严格的空值检查机制
  • 利用异常处理过程中的字符串转换触发恶意代码

利用链构造过程

调用链分析

ImmutableSetMultimap.readObject()
    → SingletonImmutableBiMap.readResolve()
        → SerializedForm.createMap()
            → Builder.put()
                → ImmutableMap.entryOf()
                    → checkEntryNotNull()
                        → String.valueOf()
                            → JSONArray.toString()
                                → DruidXADataSource.getValidationQuery()
                                    → SQL CALL 语句执行
                                        → SerializationUtils.deserialize()

详细技术分析

第一步:ImmutableSetMultimap 反序列化

ImmutableSetMultimapreadObject 方法被调用时:

  • 读取序列化数据,包括内部的 map 结构
  • 在利用链中,这个 map 是 SingletonImmutableBiMap 实例

第二步:SingletonImmutableBiMap 的 readResolve

SingletonImmutableBiMap 在反序列化时的行为:

  • 调用 readResolve 方法
  • 通过 SerializedForm.createMap 重新构建 map 对象
  • 在构建过程中,调用 Builder.put 来添加键值对

第三步:Builder.put 和 entryOf

Builder.put 方法的执行流程:

  • 调用 ImmutableMap.entryOf 创建 entry 对象
  • 该方法会检查 key 和 value 是否为 null

第四步:关键的空值检查

checkEntryNotNull 方法的作用:

  • 检查 entry 的 key 和 value 是否为 null
  • 在检查过程中,由于抛出异常,Guava 会调用 String.valueOf() 将对象转换为字符串
  • 这是整个利用链的关键转折点

第五步:触发 JSONArray.toString

字符串转换的触发机制:

  • String.valueOf() 被调用时,如果对象是 JSONArray,就会调用 JSONArray.toString() 方法
  • Jackson 的 JSONArray.toString() 方法会自动调用类中定义的 getter 方法

恶意对象构造

DruidXADataSource 利用

恶意对象选择:使用 DruidXADataSource 作为攻击载体

攻击原理

  • validationQuery 字段会在连接池验证连接时被执行
  • 在该字段中嵌入 SQL CALL 语句
  • 调用 Spring 的反序列化工具类执行构造好的 payload

具体实现

DruidXADataSource ds = new DruidXADataSource();
// 设置恶意 validationQuery,包含 SQL CALL 语句
ds.setValidationQuery("CALL malicious_procedure()");

攻击执行流程

  1. DruidXADataSource.getXAConnection() 执行 SQL 语句
  2. 调用 com.fr.third.springframework.util.SerializationUtils.deserialize 方法
  3. 进行反序列化操作,执行恶意 payload

完整利用条件

环境要求

  1. 目标系统使用 Guava 库(包含漏洞版本)
  2. 存在 Jackson 库的 JSONArray
  3. 系统中包含 Druid 连接池相关类
  4. 存在 Spring 框架的序列化工具类

技术前提

  1. 攻击者能够控制反序列化数据源
  2. 目标系统存在相应的类路径依赖
  3. 安全防护机制未阻止该特定利用链

防护建议

代码层面防护

  1. 对反序列化操作进行严格的白名单控制
  2. 更新 Guava 库到已修复漏洞的版本
  3. 对输入数据进行严格的验证和过滤

系统层面防护

  1. 使用安全管理器限制反序列化操作
  2. 实施最小权限原则,减少攻击面
  3. 定期进行安全审计和漏洞扫描

总结

该利用链巧妙地结合了多个流行框架的特性:

  • 利用 Guava 不可变集合的空值检查机制
  • 通过 Jackson 的字符串转换触发 getter 方法
  • 借助 Druid 连接池的 SQL 执行能力
  • 最终通过 Spring 的反序列化工具完成攻击

这种复杂的利用链表明,现代 Java 应用安全需要综合考虑各种组件之间的交互影响,实施纵深防御策略。

ImmutableSetMultimap 反序列化利用链深入分析 概述 本文深入分析 Guava 库中 ImmutableSetMultimap 类的反序列化利用链。该漏洞利用 Guava 不可变集合在反序列化过程中的空值检查机制,结合特定对象触发恶意代码执行。 漏洞背景 核心组件 ImmutableSetMultimap : Guava 库中的不可变多重映射集合 JSONArray : Jackson 库中的 JSON 数组实现 DruidXADataSource : 阿里 Druid 连接池的 XA 数据源实现 关键技术点 Jackson 的 JSONArray.toString() 方法会自动调用类的 getter 方法 Guava 的不可变集合在反序列化时具有严格的空值检查机制 利用异常处理过程中的字符串转换触发恶意代码 利用链构造过程 调用链分析 详细技术分析 第一步:ImmutableSetMultimap 反序列化 当 ImmutableSetMultimap 的 readObject 方法被调用时: 读取序列化数据,包括内部的 map 结构 在利用链中,这个 map 是 SingletonImmutableBiMap 实例 第二步:SingletonImmutableBiMap 的 readResolve SingletonImmutableBiMap 在反序列化时的行为: 调用 readResolve 方法 通过 SerializedForm.createMap 重新构建 map 对象 在构建过程中,调用 Builder.put 来添加键值对 第三步:Builder.put 和 entryOf Builder.put 方法的执行流程: 调用 ImmutableMap.entryOf 创建 entry 对象 该方法会检查 key 和 value 是否为 null 第四步:关键的空值检查 checkEntryNotNull 方法的作用: 检查 entry 的 key 和 value 是否为 null 在检查过程中,由于抛出异常,Guava 会调用 String.valueOf() 将对象转换为字符串 这是整个利用链的关键转折点 第五步:触发 JSONArray.toString 字符串转换的触发机制: 当 String.valueOf() 被调用时,如果对象是 JSONArray ,就会调用 JSONArray.toString() 方法 Jackson 的 JSONArray.toString() 方法会自动调用类中定义的 getter 方法 恶意对象构造 DruidXADataSource 利用 恶意对象选择 :使用 DruidXADataSource 作为攻击载体 攻击原理 : validationQuery 字段会在连接池验证连接时被执行 在该字段中嵌入 SQL CALL 语句 调用 Spring 的反序列化工具类执行构造好的 payload 具体实现 : 攻击执行流程 DruidXADataSource.getXAConnection() 执行 SQL 语句 调用 com.fr.third.springframework.util.SerializationUtils.deserialize 方法 进行反序列化操作,执行恶意 payload 完整利用条件 环境要求 目标系统使用 Guava 库(包含漏洞版本) 存在 Jackson 库的 JSONArray 类 系统中包含 Druid 连接池相关类 存在 Spring 框架的序列化工具类 技术前提 攻击者能够控制反序列化数据源 目标系统存在相应的类路径依赖 安全防护机制未阻止该特定利用链 防护建议 代码层面防护 对反序列化操作进行严格的白名单控制 更新 Guava 库到已修复漏洞的版本 对输入数据进行严格的验证和过滤 系统层面防护 使用安全管理器限制反序列化操作 实施最小权限原则,减少攻击面 定期进行安全审计和漏洞扫描 总结 该利用链巧妙地结合了多个流行框架的特性: 利用 Guava 不可变集合的空值检查机制 通过 Jackson 的字符串转换触发 getter 方法 借助 Druid 连接池的 SQL 执行能力 最终通过 Spring 的反序列化工具完成攻击 这种复杂的利用链表明,现代 Java 应用安全需要综合考虑各种组件之间的交互影响,实施纵深防御策略。