从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果
字数 2217 2025-08-26 22:11:51
Java反序列化漏洞分析:FastJson TemplatesImpl链与ysoserial jdk7u21链
前言
本文详细分析两种重要的Java反序列化漏洞利用链:
- FastJson 1.2.24中针对TemplatesImpl的利用链
- ysoserial工具中针对jdk7u21基于TemplatesImpl加动态代理的利用链
第一部分:TemplatesImpl链分析
1. TemplatesImpl类概述
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类是XSLT处理器的一部分,它可以将XSLT样式表编译成可执行的转换器。
2. 关键利用点
FastJson 1.2.24中利用链的入口点在TemplatesImpl.getOutputProperties()函数。调用链如下:
TemplatesImpl -> getOutputProperties()
TemplatesImpl -> newTransformer()
TemplatesImpl -> getTransletInstance()
3. 详细分析
getTransletInstance()函数
这是漏洞触发的核心函数,关键代码逻辑:
private Translet getTransletInstance() throws TransformerConfigurationException {
if (_name == null) return null;
if (_class == null) defineTransletClasses();
AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
return translet;
}
defineTransletClasses()函数
该函数负责加载字节码:
- 检查
_bytecodes不能为null - 获取类加载器
- 通过
defineClass加载字节码 - 检查加载类的父类必须是
ABSTRACT_TRANSLET
恶意类构造要求
恶意类必须满足:
- 继承自
AbstractTranslet - 实现
Transformer接口的两个方法 - 将恶意代码放在静态代码块或构造函数中
示例恶意类:
public class EvilClass extends AbstractTranslet {
static {
// 恶意代码
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
精简后的Payload结构
{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["恶意类字节码"],
"_name": "任意名称",
"_tfactory": {},
"_outputProperties": {}
}
第二部分:ysoserial jdk7u21链分析
1. 整体利用链
该链结合了TemplatesImpl和动态代理技术,调用链如下:
HashSet.readObject()
-> HashMap.put()
-> Proxy.hashCode()
-> AnnotationInvocationHandler.invoke()
-> AnnotationInvocationHandler.hashCodeImpl()
-> TemplatesImpl.hashCode()
-> TemplatesImpl.equals()
-> AnnotationInvocationHandler.invoke()
-> AnnotationInvocationHandler.equalsImpl()
-> 反射调用TemplatesImpl.newTransformer()
-> getTransletInstance()
-> 恶意类实例化
2. 关键组件
动态代理技术
- 定义被代理的接口及其实现类
- 定义代理类,继承
InvocationHandler - 通过
Proxy.newProxyInstance创建代理对象
AnnotationInvocationHandler
这是Java内部用于处理注解的动态代理类,关键特性:
- 继承自
InvocationHandler - 构造函数有两个可控成员变量:
type:代理的接口类型memberValues:存储键值对的Map
3. ysoserial构造过程
创建恶意TemplatesImpl对象
- 使用
ClassPool和CtClass动态构造恶意类 - 插入静态代码块包含RCE代码
- 设置父类为
AbstractTranslet - 通过反射设置
_bytecodes等字段
构造代理对象
- 创建
AnnotationInvocationHandler实例 - 设置
type为Templates接口 - 设置
memberValues为特殊构造的Map
构造最终Payload
- 创建
LinkedHashSet包含两个元素:- 恶意
TemplatesImpl对象 - 代理对象
- 恶意
- 序列化该
LinkedHashSet
4. 触发过程详解
- 反序列化时首先读取
TemplatesImpl对象 - 然后读取代理对象,触发
hashCode()调用 - 进入
AnnotationInvocationHandler.invoke() - 计算hash时触发
equals()比较 - 最终反射调用
newTransformer()触发RCE
5. 关键技巧
memberValues的键设置为"f5a5a608"是为了确保hash计算匹配- 需要精确控制hash计算过程使条件判断成立
- 通过动态代理将
equals()调用转化为newTransformer()调用
第三部分:jdk7u21与jdk7u25的差异
修复点分析
jdk7u25修复了此漏洞,关键差异在AnnotationInvocationHandler.readObject():
- 增加了对
type的校验 - 检查是否为注解类型(
isAnnotation()) - 非注解类型会抛出异常
具体修复代码
private void readObject(ObjectInputStream var1) {
try {
var1.defaultReadObject();
AnnotationType var2 = AnnotationType.getInstance(this.type);
// ...
} catch (Exception e) {
throw new InvalidObjectException("Non-annotation type in annotation serial stream");
}
}
为什么jdk7u21可利用
- 虽然
AnnotationType.getInstance()会抛出异常 - 但异常被捕获后直接返回,没有重新抛出
- 反序列化过程可以继续执行
- 动态代理对象能够成功恢复
第四部分:总结与启示
技术要点总结
- 字节码加载:通过
defineClass动态加载恶意类 - 反射机制:关键操作都依赖Java反射
- 动态代理:将方法调用转化为可控流程
- 反序列化:作为整个利用的入口点
安全启示
- 不要反序列化不可信数据
- 注意内部类的安全性
- 动态代理可能带来安全隐患
- 异常处理不当可能导致漏洞
扩展思考
- 类似的利用模式可以应用于其他链
- 理解这些技术有助于发现新漏洞
- Java安全机制需要全面考虑
附录:关键类和方法
TemplatesImpl关键方法
getOutputProperties()newTransformer()getTransletInstance()defineTransletClasses()
AnnotationInvocationHandler关键方法
invoke()hashCodeImpl()equalsImpl()readObject()
相关接口
TemplatesAbstractTransletInvocationHandler