天天看点

Java反序列化(四)Common Collection 2分析

jdk 1.7,jdk1.8也测试成功。

Commons Collections 4.0

idea

idea创建maven项目,在pom.xml添加即可

后半段链和cc1差不多,正向分析,从readObject方法开始分析。

找到关键类​<code>​java.util.PriorityQueue​</code>​的readObject方法。

Java反序列化(四)Common Collection 2分析

可以看到方法比较简单。可以看到queue[i]的值是由s.readObject方法得到的。为什么会这样,这是因为序列化的时候依次对queue[i]中的值进行序列化了,如下图。所以当反序列化的时候,也依次进行了反序列化。

Java反序列化(四)Common Collection 2分析

既然这样的话,只要我们通过反射实例化PriorityQueue类的对象,并且给queue赋值即可,,实现了queue[i]控制。

接下来进入​<code>​heapify​</code>​方法

Java反序列化(四)Common Collection 2分析

跟进​<code>​siftDown​</code>​方法,注意这里在第二个参数传入了queue[i],并且还要注意,这里进入for循环需要一个条件,就是size&gt;1,因为​<code>​size &gt;&gt;&gt; 1​</code>​进行了右移位操作,所以只有当size&gt;1的时候才会进入循环,这是第一个条件。

Java反序列化(四)Common Collection 2分析

这里的x即为queue[i],跟进​<code>​siftDownUsingComparator​</code>​方法。

Java反序列化(四)Common Collection 2分析

重点在​<code>​comparator.compare(x, (E) c)​</code>​,comparator其实是一个Comparator接口,而​<code>​org.apache.commons.collections4.comparators.TransformingComparator​</code>​实现了​<code>​Comparator​</code>​接口,重写了​<code>​compare​</code>​方法,

Java反序列化(四)Common Collection 2分析

可以看到compare方法中执行了​<code>​this.transformer.transform​</code>​。后面就是CC1链了。

分析几个关键地方

1.这里为了add了两个值主要是为了上面说到的第一个条件,size&gt;1

2.必须在add后,再反射设置​<code>​comparator​</code>​值。

这是由于在add方法中调用了offer方法。

Java反序列化(四)Common Collection 2分析

offer方法中调用了siftUp方法

Java反序列化(四)Common Collection 2分析

在siftUp方法中,需要让​<code>​comparator​</code>​为null,才会走else,走else才可以添加到queue中,否则会报错。

Java反序列化(四)Common Collection 2分析

在yso中用的CC2涉及到了另一个点:​<code>​TemplatesImpl​</code>​。jdk1.7和1.8都测试成功。

需要先去大概了解一下上面是​<code>​javassit​</code>​。

想了半天,最终还是从readObject来学习​<code>​TemplatesImpl​</code>​这条链。然后配合Poc中的代码结合来理解。

先放出完整的exp,虽然不是yso的实际代码,但原理是一样的。

我们最终序列化的是PriorityQueue的对象。所以从PriorityQueue的readObject方法来说起。

找到该方法。

Java反序列化(四)Common Collection 2分析

注意图中的​<code>​queue​</code>​变量,这个变量我们已经在exp中修改过值了。对应的exp如下。

由此可知,queue里有两个值,第一个值是​<code>​templates​</code>​,第二个值是​<code>​1​</code>​。

并且​<code>​size​</code>​变量也已经在exp中修改了,对应exp代码如下,将size修改为2。至于为什么我觉得应该不用说了,上面已经解释过了。

跟进​<code>​heapify​</code>​方法,

Java反序列化(四)Common Collection 2分析

跟进​<code>​siftDown​</code>​方法,传入了queue[i],

Java反序列化(四)Common Collection 2分析

在这里遇到了​<code>​comparator​</code>​变量,对应的exp代码如下。

而comparator如下对应exp代码如下

继续跟进​<code>​siftDownUsingComparator​</code>​方法。

Java反序列化(四)Common Collection 2分析

关键代码​<code>​comparator.compare​</code>​,通过前面的分析可知,这里的​<code>​comparator​</code>​是TransformingComparator实例化的对象,而变量x是queue[0],因为在​<code>​heapify​</code>​函数中是依次循环的,而queue[0]是exp中的​<code>​templates​</code>​,仔细对照上面的分析及exp代码。

接下来则调用的是​<code>​TransformingComparator​</code>​的​<code>​compare​</code>​方法

跟踪该方法。

Java反序列化(四)Common Collection 2分析

注意看这里的​<code>​this.transformer​</code>​对应的exp代码是,即​<code>​this.transformer​</code>​就是exp代码中的​<code>​transformer​</code>​。(注意实例化的时候传了一个参数为"newTransformer"。)

即调用了​<code>​InvokerTransformer​</code>​的​<code>​transform​</code>​方法,而​<code>​obj1​</code>​就是上面的​<code>​x​</code>​,即​<code>​templates​</code>​,

跟踪这个​<code>​transform​</code>​方法,

Java反序列化(四)Common Collection 2分析

这里分析一下:

input变量就是上面的obj1,即传过来的​<code>​templates​</code>​,而this.iMethodName的值为​<code>​newTransformer​</code>​。因为​<code>​templates​</code>​是​<code>​TemplatesImpl​</code>​类的对象,所以调用的是​<code>​TemplatesImpl.newTransformer​</code>​。

跟踪​<code>​TemplatesImpl.newTransformer​</code>​方法。

Java反序列化(四)Common Collection 2分析

跟踪​<code>​getTransletInstance​</code>​方法

Java反序列化(四)Common Collection 2分析

图中,我们看到三处地方,第一处对应的exp代码如下,想必大家都知道为什么。只要不为null就好。

第二处,必须是null,因为我们想要进入​<code>​defineTransletClasses​</code>​方法。

第三处​<code>​_class[_transletIndex].newInstance();​</code>​会执行我们构造的static代码块,后面会说到。

跟进​<code>​defineTransletClasses​</code>​方法

Java反序列化(四)Common Collection 2分析

可以看到​<code>​_bytecodes​</code>​变量,这个变量对应exp代码如下,

这么多代码就是通过javassti新建一个类,并且添加了一个static代码块,内容为​<code>​java.lang.Runtime.getRuntime().exec("calc.exe");​</code>​。如下图,这就是我们通过javassti生成的class文件。只不过在代码中,将该class转为了字节数组,即​<code>​_bytecodes​</code>​变量。

Java反序列化(四)Common Collection 2分析

继续看​<code>​defineTransletClasses​</code>​方法

Java反序列化(四)Common Collection 2分析

可以看到,上面已经将​<code>​_bytecodes​</code>​数组变成一个类了,后面判断该类的父类是否是​<code>​ABSTRACT_TRANSLET​</code>​,看下图,值为​<code>​com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet​</code>​。

Java反序列化(四)Common Collection 2分析

所以我们要在exp代码中

因为我们要进入if判断,才能执行​<code>​_transletIndex = i;​</code>​,赋值给​<code>​_transletIndex​</code>​后,​<code>​_class[_transletIndex].newInstance();​</code>​才会执行我们恶意的static代码块。

至此也应该算是分析结束了。