深入fastjson源码命令执行调试
字数 1284 2025-08-10 19:49:08
Fastjson反序列化漏洞深入分析与调试指南
1. 漏洞背景与概述
Fastjson是阿里巴巴开源的一个高性能JSON处理库,广泛用于Java应用程序中。然而,Fastjson在反序列化过程中存在安全漏洞,攻击者可以通过精心构造的JSON数据实现远程代码执行(RCE)。
本教学文档将详细分析Fastjson反序列化漏洞的原理、利用方式以及调试过程,帮助安全研究人员深入理解该漏洞。
2. 漏洞环境搭建
2.1 创建漏洞演示类
import java.util.Properties;
public class Person {
private String name;
private int age;
private String sex;
private Properties properties;
public Person() {
System.out.println("构造方法");
}
// Getter和Setter方法
public String getName() {
System.out.println("getName");
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
public int getAge() {
System.out.println("getAge");
return age;
}
public String getSex(){
System.out.println("getAddress");
return sex;
}
public Properties getProperties() throws Exception {
System.out.println("getProperties");
Runtime.getRuntime().exec("open -a /System/Applications/Calculator.app");
return properties;
}
}
2.2 反序列化测试代码
import com.alibaba.fastjson.JSON;
public class Demo {
public static void main(String[] args){
String jsonstring = "{\"@type\":\"com.FastjsonDemo.Person\",\"age\":18,\"name\":\"lili\",\"address\":\"china\",\"properties\":{}}";
Object obj = JSON.parseObject(jsonstring, Object.class);
System.out.println(obj);
}
}
3. 漏洞利用原理
3.1 关键点分析
- @type属性:Fastjson通过该属性指定要反序列化的目标类
- Getter方法触发:反序列化过程中会自动调用目标类的Getter方法
- 危险方法调用:在Getter方法中执行危险操作(如
Runtime.exec())
3.2 漏洞触发流程
- Fastjson解析JSON字符串时,发现
@type属性 - 根据
@type指定的类名加载并实例化目标类 - 为JSON中的每个属性调用对应的Setter或Getter方法
- 当调用到
getProperties()方法时,执行其中的命令
4. 详细调试分析
4.1 调试入口
在JSON.parseObject()方法处设置断点,开始调试:
Object obj = JSON.parseObject(jsonstring, Object.class);
4.2 调用栈分析
-
初始parseObject调用:
public static <T> T parseObject(String text, Class<T> clazz) { return parseObject(text, clazz); } -
重载方法调用:
public static <T> T parseObject(String json, Class<T> clazz, Feature... features) { return parseObject(json, clazz, ParserConfig.global, (ParseProcess)null, DEFAULT_PARSER_FEATURE, features); } -
核心解析方法:
public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) { // 创建解析器 DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues); // 解析对象 T value = parser.parseObject(clazz, (Object)null); // 处理解析结果 parser.handleResovleTask(value); parser.close(); return value; }
4.3 关键解析过程
-
DefaultJSONParser初始化:
- 创建
DefaultJSONParser对象 - 初始化
JSONLexer用于词法分析
- 创建
-
parseObject方法:
public <T> T parseObject(Type type, Object fieldName) { int token = this.lexer.token(); // 获取反序列化器 ObjectDeserializer derializer = this.config.getDeserializer(type); // 执行反序列化 return derializer.deserialze(this, type, fieldName); } -
反序列化器获取:
- 通过
ParserConfig.getDeserializer()获取对应类型的反序列化器 - 对于自定义类,会使用
JavaBeanDeserializer
- 通过
-
字段解析:
boolean match = this.parseField(parser, key, object, type, fieldValues);- 通过
smartMatch方法匹配字段和反序列化器 - 调用字段对应的Getter/Setter方法
- 通过
4.4 漏洞触发点
在Person.getProperties()方法中:
public Properties getProperties() throws Exception {
System.out.println("getProperties");
Runtime.getRuntime().exec("open -a /System/Applications/Calculator.app");
return properties;
}
当Fastjson解析到properties字段时:
- 检查并调用
getProperties()方法 - 方法中的
Runtime.exec()被执行 - 弹出计算器,实现命令执行
5. 漏洞防御措施
- 升级Fastjson版本:使用已修复漏洞的最新版本
- 关闭autotype功能:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false); - 使用安全模式:
ParserConfig.getGlobalInstance().addAccept("com.yourpackage.") - 输入验证:对JSON输入进行严格验证
- 使用白名单:限制可反序列化的类
6. 调试技巧与总结
-
调试关键点:
@type属性的处理- 反序列化器的获取过程
- 字段解析和Getter方法调用
-
调试工具:
- IDE调试器(IntelliJ IDEA/Eclipse)
- 条件断点
- 调用栈分析
-
学习建议:
- 多次重复调试过程,理解每个步骤
- 关注Fastjson的核心解析逻辑
- 分析不同版本间的差异
通过本教学文档,读者可以深入理解Fastjson反序列化漏洞的原理和利用方式,掌握相关的调试技巧,并学习如何防御此类漏洞。