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.findMethodReflectionUtils.invokeMethod都没有传递Method的参数,因此是无参方法和无参调用。

我们的目标是让this.MethodNamenewTransformergetOutputProperties(这两个都是public方法,findMethodinvokeMethod都没有设置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有如下方法

image-20230926143651300

那如何让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-beansObjectFactoryDelegatingInvocationHandler换成spring-aopJdkDynamicAopProxy

JdkDynamicAopProxy

image-20230926202012275
image-20230926202040784

JdkDynamicAopProxy将方法调用委托给了AdvisedSupporttarget成员

直接上POC

Ref

https://su18.org/post/ysoserial-su18-3/#spring1

Last updated

Was this helpful?