Fastjson 1.2.68 AutoCloseable 利用链深度分析
字数 1999 2025-08-30 06:50:35
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缓存并返回该类
- 解析 POC 中的实际恶意类(如
-
触发执行:
- 成功返回恶意类并触发执行
漏洞利用
利用条件
- 目标类需要实现
AutoCloseable接口 InputStream和OutputStream都实现了AutoCloseable接口且不在黑名单中- 需要找到合适的 gadget 链组合
Gadget 构造思路
-
文件路径指定:
- 需要一个通过 set 方法或构造方法指定文件路径的
OutputStream
- 需要一个通过 set 方法或构造方法指定文件路径的
-
数据写入:
- 需要一个通过 set 方法或构造方法传入字节数据的
OutputStream - 能够通过 set 方法或构造方法传入一个
OutputStream - 可以通过 write 方法将传入的字节码写入到传入的
OutputStream
- 需要一个通过 set 方法或构造方法传入字节数据的
-
触发机制:
- 需要一个通过 set 方法或构造方法传入一个
OutputStream - 能够通过调用
toString、hashCode、get、set或构造方法调用传入的OutputStream的flush方法
- 需要一个通过 set 方法或构造方法传入一个
具体利用方式
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"
}
执行流程:
- 实例化
FileOutputStream创建文件 - 实例化
FastOutputStream进行赋值 - 实例化
SnappyOutputStream调用 write 方法 - 最终完成文件写入
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 方式压缩数据
执行流程:
- 实例化
FileOutputStream创建文件 - 实例化
InflaterOutputStream(包含压缩数据) - 实例化
MarshalOutputStream - 调用父类构造函数设置 block data mode
- 最终调用
InflaterOutputStream的 write 方法写入数据
4. RCE 利用
结合文件写入功能可以实现远程代码执行,具体可参考相关文章。
防御建议
- 升级到 Fastjson 最新版本
- 关闭 AutoType 功能
- 使用白名单机制限制反序列化类
- 监控可疑的文件操作行为