Fastjson反序列化浅析(一)
字数 1529 2025-08-18 11:37:15

Fastjson反序列化漏洞分析(一)

一、Fastjson基本概念

Fastjson是一个Java语言的JSON解析库,主要功能是将JSON字符串解析为Java对象。其基本使用方式如下:

String s = "{\"param1\":\"aaa\",\"param2\":\"bbb\"}";
// 解析JSON
JSONObject jsonObject = JSON.parseObject(s);
// 原生打印
System.out.println(jsonObject);
// 获取指定的键值
System.out.println(jsonObject.getString("param1"));

Fastjson支持将JSON字符串解析为JavaBean对象:

String s = "{\"age\":\"18\",\"name\":\"yexing\"}";
Person person = JSON.parseObject(s, Person.class);
System.out.println(person.getName());

二、Fastjson的关键特性

Fastjson有一个特殊特性:可以通过@type字段指定要反序列化的类:

String s = "{\"@type\":\"org.example.Person\", \"age\":\"18\", \"name\":\"yexing\"}";
JSONObject jsonObject = JSON.parseObject(s);
System.out.println(jsonObject);

这个特性允许客户端控制反序列化的类,从而可能导致安全问题。

三、Fastjson反序列化流程分析

1. 整体流程

JSON.parseObject()主要做两件事:

  1. parse() - 序列化操作,将字符串解析为对象(调用setter)
  2. JSON.toJSON() - 将对象转为字符串(调用getter)

2. 解析流程细节

  1. 初始解析

    • 调用DefaultJSONParser()创建默认JSON解析器
    • 根据JSON字符串的字符进行解析(通过switch控制)
  2. 处理@type字段

    • 当解析到@type字段时,表示需要进行Java反序列化
    • 调用loadClass()加载指定类:
      • 先尝试从mappings缓存中加载
      • 未找到则使用APPClassLoader加载
  3. 获取反序列化器

    • 首先从缓存中查找反序列化器
    • 不在内置类型中则通过getDeserializer()获取
    • 检查类名是否在黑名单中(1.2.24以前的黑名单主要基于性能考虑)
    • 最终通过createJavaBeanDeserializer()创建JavaBean反序列化器
  4. JavaBean信息构建

    • 调用JavaBeanInfo.build()
      • 第一个循环:遍历获取setter方法
      • 第二个循环:遍历public字段
      • 第三个循环:遍历getter方法
    • 返回包含所有信息的JavaBeanInfo对象
  5. 实例创建与属性设置

    • 通过反射调用构造函数创建实例
    • 调用parseField()setValue()设置属性值(调用setter)
  6. toJSON处理

    • 调用toJSON()将对象转为字符串
    • 通过getFieldValuesMap()获取字段值
    • 调用getter.getPropertyValue()获取属性值(调用getter)

四、关键安全点分析

  1. @type字段控制

    • 允许客户端指定任意类进行反序列化
    • 这是Fastjson反序列化漏洞的根本原因
  2. 方法调用

    • 自动调用setter和getter方法
    • 可能触发危险操作
  3. 黑名单机制

    • 1.2.24版本前的黑名单不完善
    • 主要基于性能考虑而非安全考虑
  4. 动态类加载

    • 通过asmEnable开关控制动态类创建
    • 可能被利用来加载恶意类

五、漏洞利用条件

  1. 存在只有getter没有setter且返回特定类型(Map/Collection等)的方法
  2. 当满足这个条件时:
    • getOnly标志会被设为true
    • asmEnable会被设为false
    • 使用可调试的反序列化器

六、防御建议

  1. 升级到最新版本Fastjson
  2. 严格限制反序列化的类(使用白名单)
  3. 禁用@type特性(通过ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
  4. 避免在getter/setter中执行危险操作

七、总结

Fastjson的反序列化漏洞主要源于其灵活的@type特性和自动调用getter/setter的设计。理解其内部解析流程对于分析和防御相关漏洞至关重要。开发者应当谨慎使用Fastjson的反序列化功能,特别是在处理不可信的JSON输入时。

Fastjson反序列化漏洞分析(一) 一、Fastjson基本概念 Fastjson是一个Java语言的JSON解析库,主要功能是将JSON字符串解析为Java对象。其基本使用方式如下: Fastjson支持将JSON字符串解析为JavaBean对象: 二、Fastjson的关键特性 Fastjson有一个特殊特性:可以通过 @type 字段指定要反序列化的类: 这个特性允许客户端控制反序列化的类,从而可能导致安全问题。 三、Fastjson反序列化流程分析 1. 整体流程 JSON.parseObject() 主要做两件事: parse() - 序列化操作,将字符串解析为对象(调用setter) JSON.toJSON() - 将对象转为字符串(调用getter) 2. 解析流程细节 初始解析 : 调用 DefaultJSONParser() 创建默认JSON解析器 根据JSON字符串的字符进行解析(通过switch控制) 处理@type字段 : 当解析到 @type 字段时,表示需要进行Java反序列化 调用 loadClass() 加载指定类: 先尝试从mappings缓存中加载 未找到则使用APPClassLoader加载 获取反序列化器 : 首先从缓存中查找反序列化器 不在内置类型中则通过 getDeserializer() 获取 检查类名是否在黑名单中(1.2.24以前的黑名单主要基于性能考虑) 最终通过 createJavaBeanDeserializer() 创建JavaBean反序列化器 JavaBean信息构建 : 调用 JavaBeanInfo.build() : 第一个循环:遍历获取setter方法 第二个循环:遍历public字段 第三个循环:遍历getter方法 返回包含所有信息的JavaBeanInfo对象 实例创建与属性设置 : 通过反射调用构造函数创建实例 调用 parseField() 和 setValue() 设置属性值(调用setter) toJSON处理 : 调用 toJSON() 将对象转为字符串 通过 getFieldValuesMap() 获取字段值 调用 getter.getPropertyValue() 获取属性值(调用getter) 四、关键安全点分析 @type字段控制 : 允许客户端指定任意类进行反序列化 这是Fastjson反序列化漏洞的根本原因 方法调用 : 自动调用setter和getter方法 可能触发危险操作 黑名单机制 : 1.2.24版本前的黑名单不完善 主要基于性能考虑而非安全考虑 动态类加载 : 通过 asmEnable 开关控制动态类创建 可能被利用来加载恶意类 五、漏洞利用条件 存在只有getter没有setter且返回特定类型(Map/Collection等)的方法 当满足这个条件时: getOnly 标志会被设为true asmEnable 会被设为false 使用可调试的反序列化器 六、防御建议 升级到最新版本Fastjson 严格限制反序列化的类(使用白名单) 禁用 @type 特性(通过 ParserConfig.getGlobalInstance().setAutoTypeSupport(false); ) 避免在getter/setter中执行危险操作 七、总结 Fastjson的反序列化漏洞主要源于其灵活的 @type 特性和自动调用getter/setter的设计。理解其内部解析流程对于分析和防御相关漏洞至关重要。开发者应当谨慎使用Fastjson的反序列化功能,特别是在处理不可信的JSON输入时。