Spring
Spring1
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
</dependencies>MethodInvokeTypeProvider
切入点在 org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider
static class MethodInvokeTypeProvider implements TypeProvider {
private final TypeProvider provider;
private final String methodName;
private final int index;
private transient Object result;
public MethodInvokeTypeProvider(TypeProvider provider, Method method, int index) {
this.provider = provider;
this.methodName = method.getName();
this.index = index;
this.result = ReflectionUtils.invokeMethod(method, provider.getType());
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
Method method = ReflectionUtils.findMethod(this.provider.getType().getClass(), this.methodName);
this.result = ReflectionUtils.invokeMethod(method, this.provider.getType());
}
}readObject会调用this.provider.getType()返回对象的this.methodName指定的方法,这里ReflectionUtils.findMethod和ReflectionUtils.invokeMethod都没有传递Method的参数,因此是无参方法和无参调用。
我们的目标是让this.MethodName为newTransformer或getOutputProperties(这两个都是public方法,findMethod和invokeMethod都没有设置Method的可访问性),让this.provider.getType()返回TemplatesImpl
这个可以通过动态代理实现,先介绍几个调用处理器
ObjectFactoryDelegatingInvocationHandler
org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler
invoke中会把方法调用委派给objectFactory#getObject()获取到的对象。
AnnotationInvocationHandler
sun.reflect.annotation.AnnotationInvocationHandler
invoke的返回值在memberValues中找,key为method方法名。可以返回任意对象。
Weave Poc
TypeProvider#getType返回的是Type接口类,我们可以让一个动态代理类去代理Type接口。
由于接下来ReflectionUtils.invokeMethod(method, this.provider.getType());要调用newTransformer,因此我们这个代理类除了代理Type接口类,还得代理Templates接口类(才能获取到接口类的方法)
获取到的动态代理类Proxy1有如下方法

那如何让TypeProvider#getType返回我们的(Type)Proxy1呢,也是再套一层动态代理,代理TypeProvider接口类,利用AnnotationInvocationHandler返回Proxy1,即设置memberValues.put("getType", Proxy1)
Proxy1的调用处理器设置为ObjectFactoryDelegatingInvocationHandler,这样就能把newTransformer的调用委托给ObjectFactory#getObject的返回对象去调用了。
让ObjectFactory#getObject返回TemplatesImpl即可,到此有两条路可走,继续套动态代理或寻找ObjectFactory的实现类(翻了一下发现不好构造,还是没有动态代理来得优雅)
继续套一层动态代理,代理ObjectFactory<?>泛型接口,利用AnnotationInvocationHandler返回TemplatesImpl,即设置memberValues.put("getObject", TemplatesImpl)
Spring2
在Spring1链基础上有所变化,把spring-beans的ObjectFactoryDelegatingInvocationHandler换成spring-aop的JdkDynamicAopProxy
JdkDynamicAopProxy


JdkDynamicAopProxy将方法调用委托给了AdvisedSupport的target成员
直接上POC
Ref
https://su18.org/post/ysoserial-su18-3/#spring1
Last updated
Was this helpful?