从FastJ学习fastjson1.2.80反序列化
字数 1916 2025-08-29 22:41:32
Fastjson 1.2.80 反序列化漏洞深入分析与利用
漏洞背景
Fastjson 1.2.80 版本在之前版本的基础上新增了 AutoCloseable、Runnable、Readable 三个类的黑名单,导致 1.2.68 版本的利用链失效。然而,通过寻找新的期望类 Throwable 并结合新的缓存机制,仍然可以实现反序列化漏洞的利用。
核心机制
1. 缓存机制
Fastjson 反序列化符合条件的期望类时,会将以下内容添加到缓存中:
- setter 参数类型
- public 字段类型
- 构造函数参数类型
2. 绕过黑名单的关键
利用 Throwable 类作为期望类,结合缓存机制绕过黑名单检查。
漏洞利用流程
第一阶段:缓存 ProcessingUnit 类
- 通过
JSONObject.parse进入反序列化流程 - 到达
checkAutoType()方法时,直接从 Mapping 中取出Exception类 - 获取
ThrowableDeserializer类型的反序列化器 - 在
ThrowableDeserializer.deserialze方法中获取第二个@type字段中的类名 - 再次进入
checkAutoType(),此时expectClassFlag为 true - 加载
org.codehaus.groovy.control.CompilationFailedException并放入 Mapping - 通过
TypeUtils.cast进行类型转换,进入castToJavaBean - 将
ProcesssingUnit类及其反序列化器添加到IdentityHashMap缓存中
第二阶段:Groovy 利用链
- 再次进入
checkAutoType方法时,直接从deserializers中获取ProcesssingUnit类 - 返回
JavaBeanDeserializer反序列化器 - 在
deserialze方法中设置typeName为org.codehaus.groovy.tools.javac.JavaStubCompilationUnit - 设置期望类为
org.codehaus.groovy.control.ProcessingUnit - 加载
JavaStubCompilationUnit并加入 Mapping - 调用
setClasspathList设置路径 - 通过构造函数触发恶意代码执行
文件操作利用链
1. 输入流利用链
- 缓存
InputCoercionException的构造函数参数类型JsonParser - 将
JsonParser类作为期望类缓存UTF8StreamJsonParser的构造函数参数类型InputStream - 进行文件读写操作
2. 输出流利用链(适用于无 common-io 依赖环境)
- 利用
MarshalOutputStream类(继承于OutputStream) - 通过缓存
OutputStream作为期望类进行利用 - 使用
UTF8JsonGenerator(参数类型为OutputStream) - 寻找继承
Exception且参数类型为JsonGenerator的类
3. 具体利用步骤
- 构造
OutputStream的缓存链 - 传入缓存 PoC,使
deserializers缓存获得java.io.OutputStream类 OutputStream作为期望类,将后续危险类加入 Mapping 缓存- 在
autoType为 false 的情况下完成反序列化利用 - 写入文件(数据需使用 openssl zlib 方式压缩)
防御措施
- 升级到 Fastjson 最新版本
- 禁用
autoType功能 - 使用白名单机制限制反序列化的类
- 对 Fastjson 输入进行严格过滤
参考资源
总结
Fastjson 1.2.80 版本虽然增加了黑名单类,但通过 Throwable 类结合缓存机制仍然可以实现反序列化漏洞的利用。理解其缓存机制和绕过方法是防御此类漏洞的关键。开发者应当及时更新 Fastjson 版本,并采取严格的安全措施防止此类漏洞被利用。