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()
关键点分析
-
入口点:
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链分析
依赖链
SerializableTypeWrapper$MethodInvokeTypeProvider.readObject()
-> getType()
-> 动态代理调用
-> JdkDynamicAopProxy.invoke()
-> AopUtils.invokeJoinpointUsingReflection()
-> TemplatesImpl.newTransformer()
关键点分析
-
与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框架版本
- 限制反序列化操作
- 使用安全防护产品检测恶意序列化数据