Fastjson 1.2.68 AutoCloseable 利用链深度分析
字数 1999 2025-08-30 06:50:35

Fastjson 1.2.68 AutoCloseable 利用链深度分析

前言

Fastjson 反序列化漏洞的核心在于绕过 checkAutoType() 函数的检测机制。随着版本更新,Fastjson 加入了针对 ClassLoaderDataSourceRowSet 等类或接口的继承/实现检测,大大增加了 JNDI 注入的利用难度。本文深入分析 Fastjson 1.2.68 版本中通过 AutoCloseable 接口实现的利用链。

原理分析

基本利用原理

  1. 恶意类构造:首先构造一个实现 AutoCloseable 接口的恶意类
  2. POC 构造:通过特定 JSON 结构触发反序列化漏洞
  3. 绕过机制:利用 AutoCloseable 接口绕过 checkAutoType() 检测

详细绕过流程

  1. 第一次 checkAutoType 调用

    • 传入 AutoCloseable 类进行校验
    • expectClass 参数为 null
    • 直接从缓存 Mapping 中获取 AutoCloseable
    • 通过内部判断后直接返回 AutoCloseable
  2. 获取反序列化器

    • 根据 AutoCloseable 类获取 JavaBeanDeserializer
    • 调用 deserialze() 方法开始反序列化
  3. 第二次 checkAutoType 调用

    • 解析 POC 中的实际恶意类(如 VulAutoCloseable
    • 设置 expectClassjava.lang.AutoCloseable
    • 由于 AutoCloseable 不在黑名单中,设置 expectClassFlag 为 true
    • 进入 AutoType 开启时的检测逻辑
    • 通过 loadClass() 加载目标类(不开启缓存)
    • 检查目标类是否是 expectClass 的子类/实现类
    • 如果是则添加到 Mapping 缓存并返回该类
  4. 触发执行

    • 成功返回恶意类并触发执行

漏洞利用

利用条件

  1. 目标类需要实现 AutoCloseable 接口
  2. InputStreamOutputStream 都实现了 AutoCloseable 接口且不在黑名单中
  3. 需要找到合适的 gadget 链组合

Gadget 构造思路

  1. 文件路径指定

    • 需要一个通过 set 方法或构造方法指定文件路径的 OutputStream
  2. 数据写入

    • 需要一个通过 set 方法或构造方法传入字节数据的 OutputStream
    • 能够通过 set 方法或构造方法传入一个 OutputStream
    • 可以通过 write 方法将传入的字节码写入到传入的 OutputStream
  3. 触发机制

    • 需要一个通过 set 方法或构造方法传入一个 OutputStream
    • 能够通过调用 toStringhashCodegetset 或构造方法调用传入的 OutputStreamflush 方法

具体利用方式

1. 删除文件

利用特定类实现文件删除或清空:

  • 在 Windows 上需要 JDK11 以上
  • 在 RedHat 和 CentOS 下 JDK8 即可

注意:Fastjson 在类没有无参数构造函数时,会检查带参构造函数的参数是否有参数名信息,只有包含参数名的构造函数才会被认可。

检查方法:

javap -v YourClass.class | grep LocalVariableTable

2. 文件写入(方法一)

依赖:需要两个第三方依赖

Payload 结构

{
  "@type": "java.lang.AutoCloseable",
  "@type": "com.example.VulAutoCloseable",
  "file": "/path/to/file",
  "data": "base64_encoded_data"
}

执行流程

  1. 实例化 FileOutputStream 创建文件
  2. 实例化 FastOutputStream 进行赋值
  3. 实例化 SnappyOutputStream 调用 write 方法
  4. 最终完成文件写入

3. 文件写入(方法二)

特点:仅需自带库,无需额外依赖

Payload 结构

{
  "@type": "java.lang.AutoCloseable",
  "@type": "com.sun.org.apache.xml.internal.security.utils.JavaUtils",
  "file": "/path/to/file",
  "data": "zlib_compressed_data"
}

数据准备
需要使用 openssl zlib 方式压缩数据

执行流程

  1. 实例化 FileOutputStream 创建文件
  2. 实例化 InflaterOutputStream(包含压缩数据)
  3. 实例化 MarshalOutputStream
  4. 调用父类构造函数设置 block data mode
  5. 最终调用 InflaterOutputStream 的 write 方法写入数据

4. RCE 利用

结合文件写入功能可以实现远程代码执行,具体可参考相关文章。

防御建议

  1. 升级到 Fastjson 最新版本
  2. 关闭 AutoType 功能
  3. 使用白名单机制限制反序列化类
  4. 监控可疑的文件操作行为

参考资源

  1. 浅蓝师傅的分析文章
  2. scz 师傅的技术文档
  3. Rmb122 师傅的挖掘笔记
Fastjson 1.2.68 AutoCloseable 利用链深度分析 前言 Fastjson 反序列化漏洞的核心在于绕过 checkAutoType() 函数的检测机制。随着版本更新,Fastjson 加入了针对 ClassLoader 、 DataSource 、 RowSet 等类或接口的继承/实现检测,大大增加了 JNDI 注入的利用难度。本文深入分析 Fastjson 1.2.68 版本中通过 AutoCloseable 接口实现的利用链。 原理分析 基本利用原理 恶意类构造 :首先构造一个实现 AutoCloseable 接口的恶意类 POC 构造 :通过特定 JSON 结构触发反序列化漏洞 绕过机制 :利用 AutoCloseable 接口绕过 checkAutoType() 检测 详细绕过流程 第一次 checkAutoType 调用 : 传入 AutoCloseable 类进行校验 expectClass 参数为 null 直接从缓存 Mapping 中获取 AutoCloseable 类 通过内部判断后直接返回 AutoCloseable 类 获取反序列化器 : 根据 AutoCloseable 类获取 JavaBeanDeserializer 调用 deserialze() 方法开始反序列化 第二次 checkAutoType 调用 : 解析 POC 中的实际恶意类(如 VulAutoCloseable ) 设置 expectClass 为 java.lang.AutoCloseable 由于 AutoCloseable 不在黑名单中,设置 expectClassFlag 为 true 进入 AutoType 开启时的检测逻辑 通过 loadClass() 加载目标类(不开启缓存) 检查目标类是否是 expectClass 的子类/实现类 如果是则添加到 Mapping 缓存并返回该类 触发执行 : 成功返回恶意类并触发执行 漏洞利用 利用条件 目标类需要实现 AutoCloseable 接口 InputStream 和 OutputStream 都实现了 AutoCloseable 接口且不在黑名单中 需要找到合适的 gadget 链组合 Gadget 构造思路 文件路径指定 : 需要一个通过 set 方法或构造方法指定文件路径的 OutputStream 数据写入 : 需要一个通过 set 方法或构造方法传入字节数据的 OutputStream 能够通过 set 方法或构造方法传入一个 OutputStream 可以通过 write 方法将传入的字节码写入到传入的 OutputStream 触发机制 : 需要一个通过 set 方法或构造方法传入一个 OutputStream 能够通过调用 toString 、 hashCode 、 get 、 set 或构造方法调用传入的 OutputStream 的 flush 方法 具体利用方式 1. 删除文件 利用特定类实现文件删除或清空: 在 Windows 上需要 JDK11 以上 在 RedHat 和 CentOS 下 JDK8 即可 注意 :Fastjson 在类没有无参数构造函数时,会检查带参构造函数的参数是否有参数名信息,只有包含参数名的构造函数才会被认可。 检查方法: 2. 文件写入(方法一) 依赖 :需要两个第三方依赖 Payload 结构 : 执行流程 : 实例化 FileOutputStream 创建文件 实例化 FastOutputStream 进行赋值 实例化 SnappyOutputStream 调用 write 方法 最终完成文件写入 3. 文件写入(方法二) 特点 :仅需自带库,无需额外依赖 Payload 结构 : 数据准备 : 需要使用 openssl zlib 方式压缩数据 执行流程 : 实例化 FileOutputStream 创建文件 实例化 InflaterOutputStream (包含压缩数据) 实例化 MarshalOutputStream 调用父类构造函数设置 block data mode 最终调用 InflaterOutputStream 的 write 方法写入数据 4. RCE 利用 结合文件写入功能可以实现远程代码执行,具体可参考相关文章。 防御建议 升级到 Fastjson 最新版本 关闭 AutoType 功能 使用白名单机制限制反序列化类 监控可疑的文件操作行为 参考资源 浅蓝师傅的分析文章 scz 师傅的技术文档 Rmb122 师傅的挖掘笔记