盘点JDK下的动态代理在反序列化链中的利用原理
字数 2639 2025-08-22 12:23:35
JDK动态代理在反序列化链中的利用原理分析
一、动态代理基础概念
动态代理是Java提供的一种在运行时动态创建代理类和对象的技术,主要涉及以下核心类:
java.lang.reflect.Proxy:用于创建动态代理类和实例java.lang.reflect.InvocationHandler:代理实例的调用处理器接口
在反序列化漏洞利用中,动态代理主要被用来:
- 控制方法调用的行为
- 拦截特定方法的调用
- 返回精心构造的对象
- 实现方法调用的分流处理
二、关键动态代理类分析
1. CompositeInvocationHandlerImpl
特性:
- JDK自带类
- 能够根据不同的方法所属的类选择不同的InvocationHandler
- 可以看作InvocationHandler的代理
核心作用:
- 对Method方法调用进行分流处理
- 维护一个
classToInvocationHandler映射表,存储不同类对应的InvocationHandler - 提供默认的
defaultHandler处理未被特殊代理的类
处理流程:
- 获取待调用方法所属的类:
method.getDeclaringClass() - 从
classToInvocationHandler中查找对应的InvocationHandler - 如果存在特殊代理的InvocationHandler,则将方法调用传递给它的invoke方法
- 如果不存在且
defaultHandler存在,则交由默认Handler处理
2. AnnotationInvocationHandler
特性:
- JDK自带类
- 常用于反序列化gadget
- 可以指定方法返回特定的对象
核心作用:
- 对特定Method方法的返回进行预定义
- 避免某些方法调用导致的错误(如
getCompositeType调用抛异常)
实现原理:
- 通过
memberValues属性存储预定义的方法名-返回值映射 - 在invoke方法中,根据方法名从
memberValues中返回预定义的对象
限制:
- 在JDK8u71-b12之后,无法再代理非注解的接口方法
- 高版本中需要寻找替代方案
3. JdkDynamicAopProxy
来源:
- spring-aop依赖
核心作用:
- 进行方法的反射调用
- 从
AdvisedSupport.targetSource获取目标对象 - 通过反射调用目标对象的方法
关键属性:
advised:保存AdvisedSupport对象advised.targetSource:包含恶意对象(如TemplateImpl)
4. AutowireUtils$ObjectFactoryDelegatingInvocationHandler
来源:
- spring-beans依赖
核心作用:
- 进行方法的反射调用
- 从
objectFactory.getObject()获取目标对象 - 通过反射调用目标对象的方法
三、典型利用链分析
1. JSON1链
调用栈:
...
利用原理:
- 在JSONObject中包裹
cdsProxy(CompositeData代理对象) - 通过
Gadgets.createProxy创建代理对象,使用CompositeInvocationHandlerImpl作为InvocationHandler - 代理多个接口(如
CompositeData和TemplateImpl) - 反序列化时触发所有代理类中的getter方法
关键处理:
- 对于
CompositeData.getCompositeType()调用:- 使用
Gadgets.createMemoizedInvocationHandler创建特殊InvocationHandler - 避免调用抛异常导致利用失败
- 使用
- 对于其他类的getter方法:
- 使用
JdkDynamicAopProxy进行反射调用
- 使用
2. Spring1链
调用栈:
...
利用原理:
- 入口在
SerializableTypeWrapper$MethodInvokeTypeProvider.readObject - 创建
AnnotationInvocationHandler代理TypeProvider接口 - 调用
getType方法时返回另一个代理对象(ObjectFactoryDelegatingInvocationHandler) - 该代理对象实现了
Type和Templates接口 - 反射调用
newTransformer时触发命令执行
关键步骤:
- 第一个
AnnotationInvocationHandler:- 代理
TypeProvider接口 - 控制
getType方法返回ObjectFactoryDelegatingInvocationHandler代理对象
- 代理
ObjectFactoryDelegatingInvocationHandler:- 代理
Type和Templates接口 - 通过
objectFactory.getObject()获取恶意TemplateImpl对象
- 代理
- 第二个
AnnotationInvocationHandler:- 代理
ObjectFactory接口 - 控制
getObject方法返回恶意TemplateImpl对象
- 代理
四、高版本绕过技术
在JDK8u71-b12之后,AnnotationInvocationHandler无法代理非注解接口,需要替代方案:
- 使用
JdkDynamicAopProxy代理CompositeData接口的子类 - 选择JDK自带的
CompositeData实现类:javax.management.openmbean.CompositeDataSupport- 要求实现
Serializable接口
五、防御建议
- 升级JDK到最新版本
- 对反序列化操作进行严格限制
- 使用白名单机制控制可反序列化的类
- 对动态代理的使用进行监控和审计
- 避免使用不安全的JSON处理库
六、总结
动态代理在反序列化利用链中扮演着关键角色,主要通过:
- 方法调用的拦截和控制
- 特定对象的构造和返回
- 调用流程的分发和路由
- 反射调用的最终触发
理解这些动态代理类的特性和交互方式,对于分析和防御反序列化漏洞至关重要。