从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果
字数 2217 2025-08-26 22:11:51

Java反序列化漏洞分析:FastJson TemplatesImpl链与ysoserial jdk7u21链

前言

本文详细分析两种重要的Java反序列化漏洞利用链:

  1. FastJson 1.2.24中针对TemplatesImpl的利用链
  2. 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()函数

该函数负责加载字节码:

  1. 检查_bytecodes不能为null
  2. 获取类加载器
  3. 通过defineClass加载字节码
  4. 检查加载类的父类必须是ABSTRACT_TRANSLET

恶意类构造要求

恶意类必须满足:

  1. 继承自AbstractTranslet
  2. 实现Transformer接口的两个方法
  3. 将恶意代码放在静态代码块或构造函数中

示例恶意类:

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. 关键组件

动态代理技术

  1. 定义被代理的接口及其实现类
  2. 定义代理类,继承InvocationHandler
  3. 通过Proxy.newProxyInstance创建代理对象

AnnotationInvocationHandler

这是Java内部用于处理注解的动态代理类,关键特性:

  1. 继承自InvocationHandler
  2. 构造函数有两个可控成员变量:
    • type:代理的接口类型
    • memberValues:存储键值对的Map

3. ysoserial构造过程

创建恶意TemplatesImpl对象

  1. 使用ClassPoolCtClass动态构造恶意类
  2. 插入静态代码块包含RCE代码
  3. 设置父类为AbstractTranslet
  4. 通过反射设置_bytecodes等字段

构造代理对象

  1. 创建AnnotationInvocationHandler实例
  2. 设置typeTemplates接口
  3. 设置memberValues为特殊构造的Map

构造最终Payload

  1. 创建LinkedHashSet包含两个元素:
    • 恶意TemplatesImpl对象
    • 代理对象
  2. 序列化该LinkedHashSet

4. 触发过程详解

  1. 反序列化时首先读取TemplatesImpl对象
  2. 然后读取代理对象,触发hashCode()调用
  3. 进入AnnotationInvocationHandler.invoke()
  4. 计算hash时触发equals()比较
  5. 最终反射调用newTransformer()触发RCE

5. 关键技巧

  1. memberValues的键设置为"f5a5a608"是为了确保hash计算匹配
  2. 需要精确控制hash计算过程使条件判断成立
  3. 通过动态代理将equals()调用转化为newTransformer()调用

第三部分:jdk7u21与jdk7u25的差异

修复点分析

jdk7u25修复了此漏洞,关键差异在AnnotationInvocationHandler.readObject()

  1. 增加了对type的校验
  2. 检查是否为注解类型(isAnnotation())
  3. 非注解类型会抛出异常

具体修复代码

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可利用

  1. 虽然AnnotationType.getInstance()会抛出异常
  2. 但异常被捕获后直接返回,没有重新抛出
  3. 反序列化过程可以继续执行
  4. 动态代理对象能够成功恢复

第四部分:总结与启示

技术要点总结

  1. 字节码加载:通过defineClass动态加载恶意类
  2. 反射机制:关键操作都依赖Java反射
  3. 动态代理:将方法调用转化为可控流程
  4. 反序列化:作为整个利用的入口点

安全启示

  1. 不要反序列化不可信数据
  2. 注意内部类的安全性
  3. 动态代理可能带来安全隐患
  4. 异常处理不当可能导致漏洞

扩展思考

  1. 类似的利用模式可以应用于其他链
  2. 理解这些技术有助于发现新漏洞
  3. Java安全机制需要全面考虑

附录:关键类和方法

TemplatesImpl关键方法

  • getOutputProperties()
  • newTransformer()
  • getTransletInstance()
  • defineTransletClasses()

AnnotationInvocationHandler关键方法

  • invoke()
  • hashCodeImpl()
  • equalsImpl()
  • readObject()

相关接口

  • Templates
  • AbstractTranslet
  • InvocationHandler
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() 函数。调用链如下: 3. 详细分析 getTransletInstance()函数 这是漏洞触发的核心函数,关键代码逻辑: defineTransletClasses()函数 该函数负责加载字节码: 检查 _bytecodes 不能为null 获取类加载器 通过 defineClass 加载字节码 检查加载类的父类必须是 ABSTRACT_TRANSLET 恶意类构造要求 恶意类必须满足: 继承自 AbstractTranslet 实现 Transformer 接口的两个方法 将恶意代码放在静态代码块或构造函数中 示例恶意类: 精简后的Payload结构 第二部分:ysoserial jdk7u21链分析 1. 整体利用链 该链结合了TemplatesImpl和动态代理技术,调用链如下: 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() ) 非注解类型会抛出异常 具体修复代码 为什么jdk7u21可利用 虽然 AnnotationType.getInstance() 会抛出异常 但异常被捕获后直接返回,没有重新抛出 反序列化过程可以继续执行 动态代理对象能够成功恢复 第四部分:总结与启示 技术要点总结 字节码加载 :通过 defineClass 动态加载恶意类 反射机制 :关键操作都依赖Java反射 动态代理 :将方法调用转化为可控流程 反序列化 :作为整个利用的入口点 安全启示 不要反序列化不可信数据 注意内部类的安全性 动态代理可能带来安全隐患 异常处理不当可能导致漏洞 扩展思考 类似的利用模式可以应用于其他链 理解这些技术有助于发现新漏洞 Java安全机制需要全面考虑 附录:关键类和方法 TemplatesImpl关键方法 getOutputProperties() newTransformer() getTransletInstance() defineTransletClasses() AnnotationInvocationHandler关键方法 invoke() hashCodeImpl() equalsImpl() readObject() 相关接口 Templates AbstractTranslet InvocationHandler