| 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完成利用。