Spring-beans&spring-core
java8低版本或者Java7,spring-4.1.4RELEASE
AutoWiredUtils$ObjectFactoryDelegatingInvocationHandler
这是个代理类,其构造函数接收一个ObjectFactory,并赋值给this.objectFactory
invoke会调用objectFactory#getObject返回的值来调用代理的方法
AnnotationInvocationHandler
其构造函数接收一个map
invoke会返回你代理方法的名字对应的键值
MethodInvokeTypeProvider
org.springframework.core版本为4.1.4时源码如下
1 | private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { |
如果this.provider.getType()可控,那么就能将getType()返回值变成TemplatesImpl恶意类,method改成newTransformer执行恶意代码
因为getType()返回的不是泛型,而是TypeProvider类,所以要getType()要先返回一个类型为TypeProvider的代理类,所以this.provider要为map键名为getType,键值为类型为Type的ObjectFactoryDelegatingInvocationHandler代理对象的AnnotationInvocationHandler(其实我有点疑惑为什么要用ObjectFactoryDelegatingInvocationHandler,用AnnotationInvocationHandler感觉也行)。
POC
1 | public class Spring1 { |
Spring-aop
也是Java8低版本或者Java7,spring-aop4.1.4.RELEASE
将ObjectFactoryDelegatingInvocationHandler换成了JdkDynamicAopProxy
调用 AopUtils#invokeJoinpointUsingReflection() 方法反射调用对象的 method 方法并返回。
方法里就是简单的反射调用。
一切尽在不言中
另一条aop链(因为是边做边写的,所以前面有些地方并不是对的,不用过多纠结,看到最后就明白了,虽然但是看到最后也不一定明白)
sink点是org.springframework.aop.aspectj.AbstractAspectJAdvice 类中的 invokeAdviceMethodWithGivenArgs
要想invoke调用我们想要的Method,要控制this.aspectJAdviceMethod属性为我们想要触发的方法,this.aspectInstaceFactory.getInstanceFactory()为我们想要调用的实例。actualArgs暂时可以不管,因为可以考虑调用无参函数。
现在看看谁调用了这个方法。
我感觉这两个方法没有任何区别
谁调用了invokeAdviceMethod?
我感觉第一个类-AspectJAfterAdvice调用的方法最常用,因为是invoke,而且参数也简单,虽然AspectJAfterThrowingAdvice也是其中的invoke方法调用,但是这个类名字里面带一个Throwing,我感觉是跟异常相关的,可能不太好构造payload
因为是invoke,自然就想到了动态代理,但是这个类并不是一个代理类
看看有谁调用了这个方法,巧了,调用这个invoke方法的就是一个代理类的proceed
显而易见,要把bm.interceptor弄成AspectJAfterAdvice的实例。
在上图可以看见interceptorOrInterceptionAdvice被赋值给了dm,
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex)被赋值给了interceptorOrInterceptionAdvice,所以要让这个get方法返回AspectJAfterAdvice实例
这是个List泛型我们可以考虑搞一个实现List的动态代理,这个动态代理的get方法会返回一个AspectJAfterAdvice
但是我突然发现AspectJAfterAdvice没有继承InterceptorAndDynamicMethodMatcher(dm被赋值的时候被强转成这个类了),如果返回的是AspectJAfterAdvice这怎么强转?(其实在前面的图中可以看到proceed方法中还有一个地方也调用了invoke,所以调用链中并没有这一段)
因为我是为了解justdeserialize那道题来看这道题的,我看了看相关的wp发现并没有解释这个地方的,我打算跟着wp,先解决了invokeAdviceMethodWithGivenArgs中调用方法的实例如何获取再说
要使this.aspectInstanceFactory.getAspectInstance()返回一个我们想要的恶意类实例
AspectInstanceFactory是一个接口,
这个方法有一堆的实现类,该挑谁呢?
试试第一个
返回了属性aspectClass的实例
看着还行,感觉这个类能用所以给这个属性赋值SimpleAspectInstanceFactory的实例就行(其实并不行,因为这个类没实现serializable)
回到ReflectiveMethodInvocation这个类,你会发现他也没有实现serializable接口,所以需要某个方法动态创建它
并且ReflectiveMethodInvocation#proceed有两个地方调用了invoke,我前面还在困惑如何强转,结果链子的调用过程都不经过那里。
看亮着的黄黄的括号,其实
1 | Object interceptorOrInterceptionAdvice = |
这一步之后直接就到186行了,这里强转成MethodInterceptor,但是前文说的是将this.interceptorsAndDynamicMethodMatchers.get()返回AbstractJAfterAdvice实例,但是呢,这个类并没有实现MethodInterceptor接口。所以要换个类
前文说到两个调用invokeAdviceMethodWithGivenArgs的invokeAdviceMethod方法其实基本上是一样的,前文我只看了调用第一个invokeAdviceMethod的类,但是我没看第二个
而这个AspectJAroundAdvice是实现了MethodInterceptor的,所以能成功强转,所以get要返回一个AspectJAroundAdvice实例
List的get方法一般都是从List中拿一个东西出来,这个get有个参数++this.currentInterceptorIndex,这个属性在这个类中是个定值-1,++之后就是0。这个先不管放这
因为ReflectiveMethodInvocation没有实现serializable,所以需要动态创建一下
而JdkDynamicAopProxy#invoke就创建了ReflectiveMethodInvocation实例,并且调用了proceed方法
可以看见chain当作了构造函数的参数,所以要往chain里面加恶意类AspectJAroundAdvice
上图可以看到chain的赋值过程,进入赋值的方法
可以看到返回的是this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()进入这个方法
通过 org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors 来获取其返回值的。
advisor是AdvisedSupport.advisors的值,所以要控制AdvisedSupport.advisors的值,根据上图可知要满足实现了Advisor和MethodInterceptor接口,而AspectJAroundAdvice只实现了MethodInterceptor,所以还要个代理类代替一下。
其实我对最后这两个方法这么长一段代码并没有很理解,我也不是很想理解。
现在要找一个类来触发JdkDynamicAopProxy#invoke,但是JdkDynamicAopProxy是private,我对其类加载之后对它的编译类型该用啥?而且谁来触发其invoke方法呢
捋一下:JdkDynamicAopProxy#invoke-ReflectiveMethodInvocation#proceed-AspectJAroundAdvice#invoke-AbstractAspectJAdvice#invokeAdviceMethodWithArgs
因为JdkDynamicAopProxy#invoke在调用proceed方法时传了个参数List<?>chain,而chain会在proceed方法中被遍历,并调用invoke方法,所以我们要往chain中添加AspectJAroundAdvice实例。但是因为并不清楚谁来调用了JdkDynamicAopProxy#invoke,所以还是得搞清楚整个链子才能逻辑清晰的构造poc。
所以谁来调用invoke方法呢?
根据这篇文章的上一条链子,可以用MethodInvokeTypeProvider#readObject来触发,但是这道题的core版本太高了,它的readObject改版了,不能用来触发了,要换一个
不行了看不懂,放弃了
About this Post
This post is written by DashingBug, licensed under CC BY-NC 4.0.