java反序列化之yso中的spring链子分析及利用
字数 2156 2025-08-29 22:41:10

Java反序列化之YSO中的Spring链分析及利用

前言

本文详细分析Spring框架中的两条反序列化利用链(Spring1和Spring2),以及相关的利用技巧。分析基于Java 8u65版本。

Spring1链分析

适用范围

  • Spring版本:3.0.0到4.1.4

依赖链

SerializableTypeWrapper.MethodInvokeTypeProvider.readObject()
  -> getType()
    -> 动态代理调用
      -> AnnotationInvocationHandler.invoke()
        -> AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke()
          -> TemplatesImpl.newTransformer()

关键点分析

  1. 入口点SerializableTypeWrapper.MethodInvokeTypeProvider.readObject()

    • 通过反射完成方法调用
    • 目标是调用TemplatesImpl.newTransformer()实现任意类加载
  2. getType()方法

    • 返回this.result,但result是transient不可序列化
    • 需要通过动态代理控制返回值
  3. 动态代理利用

    • 使用AnnotationInvocationHandler作为InvocationHandler
    • 通过控制memberValues属性返回特定对象
    • 需要返回同时实现TypeTemplates接口的动态代理对象
  4. 关键InvocationHandler

    • AutowireUtils.ObjectFactoryDelegatingInvocationHandler
    • 关键代码:return method.invoke(this.objectFactory.getObject(), args);
    • 需要控制this.objectFactory.getObject()返回TemplatesImpl对象

利用步骤

  1. 构造TemplatesImpl对象
  2. 创建动态代理对象:
    • 第一层代理:实现TypeTemplates接口
    • 第二层代理:控制getObject()方法返回TemplatesImpl对象
  3. 通过反射调用newTransformer()方法

调试过程

  1. 调用getType()方法时跳转到InvocationHandler.invoke()
  2. memberValues中获取getType的值(实现TypeTemplates接口的代理对象)
  3. 通过ReflectionUtils.findMethod获取newTransformer方法
  4. 调用invokeMethod时进入ObjectFactoryDelegatingInvocationHandler.invoke()
  5. 通过代理对象获取TemplatesImpl实例
  6. 最终调用TemplatesImpl.newTransformer()实现任意类加载

Spring2链分析

依赖链

SerializableTypeWrapper$MethodInvokeTypeProvider.readObject()
  -> getType()
    -> 动态代理调用
      -> JdkDynamicAopProxy.invoke()
        -> AopUtils.invokeJoinpointUsingReflection()
          -> TemplatesImpl.newTransformer()

关键点分析

  1. 与Spring1的区别

    • 使用JdkDynamicAopProxy代替ObjectFactoryDelegatingInvocationHandler
    • 证明ObjectFactoryDelegatingInvocationHandler不是唯一选择
  2. JdkDynamicAopProxy.invoke()

    • 关键代码:retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
    • target来自targetSource.getTarget()
    • targetSource通过AdvisedSupport.setTarget()设置
  3. 利用方式

    • 设置targetTemplatesImpl对象
    • 最终反射调用TemplatesImpl.newTransformer()

调试过程

  1. 调用invokeMethod时进入JdkDynamicAopProxy.invoke()
  2. 获取targetTemplatesImpl对象)
  3. 通过invokeJoinpointUsingReflection反射调用newTransformer方法

攻击面拓展

替代TemplatesImpl的方案

TemplatesImpl类被禁用时,可以考虑与JNDI注入结合实现远程类加载。

利用类:com.sun.jndi.ldap.LdapAttribute

  1. 关键方法getAttributeDefinition()

    • 内部调用lookup()
    • 继承自BasicAttribute
    • 实现Attribute接口
  2. 优势

    • 方法定义在接口中(符合动态代理要求)
    • 可以触发JNDI查找

利用步骤

  1. 构造LdapAttribute对象
  2. 设置恶意LDAP服务器
  3. 通过动态代理触发getAttributeDefinition()方法
  4. 触发远程类加载

总结

  1. 核心原理

    • 两条链都依赖动态代理机制
    • 通过多层代理控制方法调用
    • 最终目标是实现任意代码执行
  2. 学习建议

    • 先掌握动态代理原理再学习这两条链
    • 理解Java反射机制
    • 熟悉Spring框架内部实现
  3. 扩展思路

    • 可以探索其他InvocationHandler的利用方式
    • 寻找更多可替代TemplatesImpl的类
    • 结合其他漏洞利用技术(如JNDI注入)
  4. 防御建议

    • 升级Spring框架版本
    • 限制反序列化操作
    • 使用安全防护产品检测恶意序列化数据
Java反序列化之YSO中的Spring链分析及利用 前言 本文详细分析Spring框架中的两条反序列化利用链(Spring1和Spring2),以及相关的利用技巧。分析基于Java 8u65版本。 Spring1链分析 适用范围 Spring版本:3.0.0到4.1.4 依赖链 关键点分析 入口点 : SerializableTypeWrapper.MethodInvokeTypeProvider.readObject() 通过反射完成方法调用 目标是调用 TemplatesImpl.newTransformer() 实现任意类加载 getType()方法 返回 this.result ,但result是transient不可序列化 需要通过动态代理控制返回值 动态代理利用 使用 AnnotationInvocationHandler 作为InvocationHandler 通过控制 memberValues 属性返回特定对象 需要返回同时实现 Type 和 Templates 接口的动态代理对象 关键InvocationHandler AutowireUtils.ObjectFactoryDelegatingInvocationHandler 关键代码: return method.invoke(this.objectFactory.getObject(), args); 需要控制 this.objectFactory.getObject() 返回 TemplatesImpl 对象 利用步骤 构造 TemplatesImpl 对象 创建动态代理对象: 第一层代理:实现 Type 和 Templates 接口 第二层代理:控制 getObject() 方法返回 TemplatesImpl 对象 通过反射调用 newTransformer() 方法 调试过程 调用 getType() 方法时跳转到 InvocationHandler.invoke() 从 memberValues 中获取 getType 的值(实现 Type 和 Templates 接口的代理对象) 通过 ReflectionUtils.findMethod 获取 newTransformer 方法 调用 invokeMethod 时进入 ObjectFactoryDelegatingInvocationHandler.invoke() 通过代理对象获取 TemplatesImpl 实例 最终调用 TemplatesImpl.newTransformer() 实现任意类加载 Spring2链分析 依赖链 关键点分析 与Spring1的区别 使用 JdkDynamicAopProxy 代替 ObjectFactoryDelegatingInvocationHandler 证明 ObjectFactoryDelegatingInvocationHandler 不是唯一选择 JdkDynamicAopProxy.invoke() 关键代码: retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); target 来自 targetSource.getTarget() targetSource 通过 AdvisedSupport.setTarget() 设置 利用方式 设置 target 为 TemplatesImpl 对象 最终反射调用 TemplatesImpl.newTransformer() 调试过程 调用 invokeMethod 时进入 JdkDynamicAopProxy.invoke() 获取 target ( TemplatesImpl 对象) 通过 invokeJoinpointUsingReflection 反射调用 newTransformer 方法 攻击面拓展 替代TemplatesImpl的方案 当 TemplatesImpl 类被禁用时,可以考虑与JNDI注入结合实现远程类加载。 利用类:com.sun.jndi.ldap.LdapAttribute 关键方法 : getAttributeDefinition() 内部调用 lookup() 继承自 BasicAttribute 实现 Attribute 接口 优势 方法定义在接口中(符合动态代理要求) 可以触发JNDI查找 利用步骤 构造LdapAttribute对象 设置恶意LDAP服务器 通过动态代理触发 getAttributeDefinition() 方法 触发远程类加载 总结 核心原理 两条链都依赖动态代理机制 通过多层代理控制方法调用 最终目标是实现任意代码执行 学习建议 先掌握动态代理原理再学习这两条链 理解Java反射机制 熟悉Spring框架内部实现 扩展思路 可以探索其他InvocationHandler的利用方式 寻找更多可替代TemplatesImpl的类 结合其他漏洞利用技术(如JNDI注入) 防御建议 升级Spring框架版本 限制反序列化操作 使用安全防护产品检测恶意序列化数据