1 | 最近在复习反序列化利用链的知识,尽管之前分析过spring1的利用链,再回头看还是发现其构造过程非常的精彩,再加上分析Spring利用链的文章比较少,因此决定写下Spring1反序列化利用链的分析过程。 |
分析过程
漏洞的sink在MethodInvokeTypeProvider#readObject
中这里通过反射完成方法调用,按照我们之前分析利用链的经验,遇到任意调用的反射肯定是想往Templates#newTransformer
上构造,因为只有TemplatesImpl
才能触发类加载并执行任意代码而不仅仅是简单的命令执行。
1 | private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { |
要完成这种方式的利用,我们需要让findMethod
返回newTransformer
方法,并且让this.provider.getType()
返回我们构造好的TempletesImpl
对象。
1 | public static Object invokeMethod(Method method, Object target) { |
那么如何让this.provider.getType()
返回一个TemplatesImpl
对象呢?肯定是需要使用动态代理,当调用到getType
时通过InvocationHandler
的处理让目标返回TemplatesImpl
。在AnnotationInvocationHandler#invoke
中可以通过控制memberValues
的属性值来控制返回的对象。
1 | public Object invoke(Object var1, Method var2, Object[] var3) { |
但是我们回头去看yso中spring1的利用链却发现并没有我们想象的那么简单,为什么会这么复杂?直接在创建动态代理时将getType
的value换为templates不可以吗?
实际上是不行的,因为getType方法已经明确了返回的对象类型是Type
类型而我们直接返回TemplatesImpl
类型会导致类型转换错误而失败。所以当调用getType
时我们还要返回一个动态代理对象。这个对象要同时实现Type
和Templates
接口。那么要选哪个InvocationHandler
呢?如何才能在反射调用这个代理对象的newTransformer
方法时能调用到我们的TemplatesImpl对象的newTransformer
方法。也就是说我们需要在这个InvocationHandler#invoke
方法中能够获取TemplatesImpl
对象并反射调用。
漏洞作者找到了ObjectFactoryDelegatingInvocationHandler
,只要我们能控制this.objectFactory.getObject()
的返回结果为构造好的TemplateImpl
对象即可。
1 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
所以我们要创建objectFactory
的动态代理并且让Handler为AnnocationInvocationHandler
并且设置memberValue
属性中getObject
为key,value为TemplatesImpl
对象。
总结
Spring1这条链算是把动态代理玩明白了,通过嵌套了多层代理。通过创建同时实现Type
和Templetes
接口的代理类来使目标可以获取到newTransformer
的Method对象,最后又利用ObjectFactoryDelegatingInvocationHandler
动态获取TemplatesImpl
对象反射调用newTransformer
完成利用。