Fastjson反序列化RCE核心-四个关键点分析
字数 2257 2025-08-25 22:58:56

Fastjson反序列化RCE核心分析

0x01 前言

Fastjson是阿里巴巴开源的一个Java JSON解析/生成库,具有以下特点:

  • 高性能的JSON处理能力
  • 提供简单的toJSONString()和parseObject()方法
  • 支持任意Java对象转换
  • 广泛支持Java泛型
  • 支持复杂对象结构

由于Fastjson在国内广泛使用,一旦出现安全漏洞影响范围极大。本文将从四个关键点深入分析Fastjson反序列化RCE漏洞的核心原理。

0x02 四个关键点分析

1. 词法解析

Fastjson的词法解析是反序列化过程中的重要环节,主要涉及以下内容:

解析流程

  1. 通过JSON.parse(text)开始解析,使用默认配置DEFAULT_PARSER_FEATURE
  2. 创建DefaultJSONParser实例,内部使用JSONScanner进行词法解析
  3. JSONScanner继承自JSONLexerBase,为性能优化做了特别处理

关键变量

  • text: JSON文本数据
  • len: 文本长度
  • token: 当前解析到的数据类型
  • ch: 当前读取到的字符
  • bp: 当前字符索引
  • sbuf: 正在解析的段数据(char数组)
  • sp: sbuf最后一个数据的索引

特殊字符处理

Fastjson对JSON字符串中的转义字符有特殊处理:

  • \0 \1 \2 \3 \4 \5 \6 \7 \b \t \n \r等双字节字符会被转换为单字符
  • \f \F双字符都会转成单字符\f
  • \v双字符转成\u000B单字符
  • \x..四字符16进制数读取转成单字符
  • \u....六字符16进制数读取转成单字符

绕过技巧

利用\x\u的词法处理可以绕过某些过滤:

@\u0074ype -> @type
@\x74ype -> @type

2. 构造方法选择

Fastjson在反序列化时需要选择合适的构造方法实例化对象:

构造方法选择逻辑

  1. 首先尝试获取defaultConstructor
    • 无参构造方法
    • 或单参数且参数类型为自身类的构造方法
  2. 如果没有defaultConstructor,则遍历查找creatorConstructor
    • 必须是public方法
    • 使用ASM获取参数名不为空
    • 选择最后一个符合条件的构造方法

特殊类处理

以下类会直接作为creatorConstructor

  • org.springframework.security.web.authentication.WebAuthenticationDetails
  • org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
  • org.springframework.security.core.authority.SimpleGrantedAuthority

3. 缓存绕过

Fastjson的checkAutoType检查机制可以通过缓存绕过:

检查流程

  1. typeName进行基本检查(长度等)
  2. 检查期望类expectClass
  3. 进行黑白名单检查
  4. 尝试从缓存中获取类:
    • TypeUtils.getClassFromMapping
    • deserializers.findClass
    • typeMapping.get

关键绕过点

  1. autoTypeSupport为true时,会缓存加载的类到mappings
    if (clazz == null && (autoTypeSupport || jsonType || expectClassFlag)) {
        boolean cacheClass = autoTypeSupport || jsonType;
        clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
    }
    
  2. 通过两次反序列化:
    • 第一次:虽然会抛出异常,但已将类缓存到mappings
    • 第二次:直接从缓存获取,绕过后续检查

绕过限制

即使绕过缓存,仍需满足:

  • 不能是ClassLoaderDataSourceRowSet等危险类
  • 如果creatorConstructor不为空且autoTypeSupport为true,仍会抛出异常

4. 反射调用

反序列化的最后阶段通过反射调用完成攻击链:

FieldInfo构建

  1. 三种情况下会创建FieldInfo
    • 基于JSONCreator注解的构造方法
    • 工厂方法
    • 普通构造方法
  2. FieldInfo有多种构造方法,其中包含Method参数的构造方法可能导致方法调用

方法收集逻辑

  1. 第一遍收集setter方法:
    • 跳过静态方法
    • 跳过返回值类型不符合的方法
    • 处理JSONField注解
    • 处理常规setter方法(方法名长度>4,以"set"开头)
  2. 第二遍收集getter方法:
    • 跳过静态方法
    • 方法名长度>4且以"get"开头
    • 无参数
    • 返回值类型为特定集合类

反序列化执行

  1. 如果token为},直接反射实例化返回
  2. 如果token为[,进行数组处理
  3. 调用构造方法实例化对象
  4. 通过FieldDeserializer处理字段:
    • 对于method不为空的fieldInfo
      • 如果getOnly为false,直接反射执行method
      • 如果getOnly为true,检查返回类型后反射执行
    • 对于method为空的fieldInfo,直接设置字段值

0x03 总结

Fastjson反序列化RCE漏洞的核心在于:

  1. 利用词法解析特性绕过过滤
  2. 选择合适的构造方法实例化对象
  3. 通过缓存机制绕过安全检查
  4. 通过反射调用触发攻击链

理解这四个关键点可以帮助我们更好地分析Fastjson漏洞,也能帮助开发人员编写更安全的代码。

Fastjson反序列化RCE核心分析 0x01 前言 Fastjson是阿里巴巴开源的一个Java JSON解析/生成库,具有以下特点: 高性能的JSON处理能力 提供简单的toJSONString()和parseObject()方法 支持任意Java对象转换 广泛支持Java泛型 支持复杂对象结构 由于Fastjson在国内广泛使用,一旦出现安全漏洞影响范围极大。本文将从四个关键点深入分析Fastjson反序列化RCE漏洞的核心原理。 0x02 四个关键点分析 1. 词法解析 Fastjson的词法解析是反序列化过程中的重要环节,主要涉及以下内容: 解析流程 通过 JSON.parse(text) 开始解析,使用默认配置 DEFAULT_PARSER_FEATURE 创建 DefaultJSONParser 实例,内部使用 JSONScanner 进行词法解析 JSONScanner 继承自 JSONLexerBase ,为性能优化做了特别处理 关键变量 text : JSON文本数据 len : 文本长度 token : 当前解析到的数据类型 ch : 当前读取到的字符 bp : 当前字符索引 sbuf : 正在解析的段数据(char数组) sp : sbuf最后一个数据的索引 特殊字符处理 Fastjson对JSON字符串中的转义字符有特殊处理: \0 \1 \2 \3 \4 \5 \6 \7 \b \t \n \r 等双字节字符会被转换为单字符 \f \F 双字符都会转成单字符 \f \v 双字符转成 \u000B 单字符 \x.. 四字符16进制数读取转成单字符 \u.... 六字符16进制数读取转成单字符 绕过技巧 利用 \x 和 \u 的词法处理可以绕过某些过滤: 2. 构造方法选择 Fastjson在反序列化时需要选择合适的构造方法实例化对象: 构造方法选择逻辑 首先尝试获取 defaultConstructor : 无参构造方法 或单参数且参数类型为自身类的构造方法 如果没有 defaultConstructor ,则遍历查找 creatorConstructor : 必须是public方法 使用ASM获取参数名不为空 选择最后一个符合条件的构造方法 特殊类处理 以下类会直接作为 creatorConstructor : org.springframework.security.web.authentication.WebAuthenticationDetails org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken org.springframework.security.core.authority.SimpleGrantedAuthority 3. 缓存绕过 Fastjson的 checkAutoType 检查机制可以通过缓存绕过: 检查流程 对 typeName 进行基本检查(长度等) 检查期望类 expectClass 进行黑白名单检查 尝试从缓存中获取类: TypeUtils.getClassFromMapping deserializers.findClass typeMapping.get 关键绕过点 当 autoTypeSupport 为true时,会缓存加载的类到 mappings : 通过两次反序列化: 第一次:虽然会抛出异常,但已将类缓存到 mappings 第二次:直接从缓存获取,绕过后续检查 绕过限制 即使绕过缓存,仍需满足: 不能是 ClassLoader 、 DataSource 、 RowSet 等危险类 如果 creatorConstructor 不为空且 autoTypeSupport 为true,仍会抛出异常 4. 反射调用 反序列化的最后阶段通过反射调用完成攻击链: FieldInfo构建 三种情况下会创建 FieldInfo : 基于 JSONCreator 注解的构造方法 工厂方法 普通构造方法 FieldInfo 有多种构造方法,其中包含 Method 参数的构造方法可能导致方法调用 方法收集逻辑 第一遍收集setter方法: 跳过静态方法 跳过返回值类型不符合的方法 处理 JSONField 注解 处理常规setter方法(方法名长度>4,以"set"开头) 第二遍收集getter方法: 跳过静态方法 方法名长度>4且以"get"开头 无参数 返回值类型为特定集合类 反序列化执行 如果token为 } ,直接反射实例化返回 如果token为 [ ,进行数组处理 调用构造方法实例化对象 通过 FieldDeserializer 处理字段: 对于 method 不为空的 fieldInfo : 如果 getOnly 为false,直接反射执行method 如果 getOnly 为true,检查返回类型后反射执行 对于 method 为空的 fieldInfo ,直接设置字段值 0x03 总结 Fastjson反序列化RCE漏洞的核心在于: 利用词法解析特性绕过过滤 选择合适的构造方法实例化对象 通过缓存机制绕过安全检查 通过反射调用触发攻击链 理解这四个关键点可以帮助我们更好地分析Fastjson漏洞,也能帮助开发人员编写更安全的代码。