CommonsCollections2反序列化链分析

经过CC1和URLDNS两条链子的洗礼,从CC2开始打算自主调试分析

复现

依赖:commons-collections4-4.0.jar

分析

1
2
3
4
5
6
7
8
9
10
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
...
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
*/

Gadgets.createTemplatesImpl( )

image.png

跟进

image.png

这里稍有复杂,先一步一步分析

首先实例化了class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

image.png

初始化ClassPool对象,插入ClassPath

image.png

image.png

通过ClassPool实例的.get()方法,获取CtClass对象

image.png

image.png

这个类作为基类,下面的操作都是基于此进行修改

为CtClass添加一个静态块,当这个类被实例化的时候,静态块内代码会执行,也就是我们传入的恶意命令

image.png

为这个类重新命名

image.png

获取到AbstTranslet类并将其设置为刚刚类的父类

image.png

添加一行输出,查看刚刚系一列操作最后得到的Class

image.png

这个时候就能很容易的把上面的各种Javassist的操作对应起来。Ysoserial用JAVAssist操作来动态修改了这个Class并且加入了一个会被自动加载的,存有恶意代码的静态块。

把字节码加载到实例对象里面,用Reflections.setFieldValue设置成templates域值

image.png

image.png

返回templates对象,方法结束

new InvokerTransformer( )

实例化InvokerTransformer

根据注释,这里只是模仿了method name,就是说还没有armed攻击载荷。

toString方法也不是想要反射调用的方法,只是占位。

image.png

关于InvokerTransformer在CC1里面分析过了,这里不再赘述,其transform方法可以反射调用,为CC的最根本的漏洞成因。

new PriorityQueue( )

image.png

新建一个优先级队列https://www.cainiaojc.com/java/java-priorityqueue.html

初始化的时候将新建的TransformingComparator作为比较器传入

image.png

当我们跟进TransformingComparator的时候,很清晰的能看到它的compare方法,调用了比较的两个对象的transform方法,这不就来了吗,初始化TransformingComparator的时候,传入的transformer是InvokerTransformer实例,这里调用的就是InvokerTransformer.transform方法,实现反射调用image.png

但是现在这个方法有点没头没尾的,哪里调用了compare,传入的两个参数又是啥,先看ysoserial怎么处理

Reflections.setFieldValue( )

image.png

之前占位的toString被更改为newTransFormer

获取到了刚实例化的优先级字段的域值,进行修改

image.png

image.png

数组第一个元素变为刚刚包含了恶意字节码的templates对象,他就是上面用来compare的object对象

这两个赋值操作让我一下豁然开朗啊!ysoserial就是这个模式,前面用占位符避免在payload生成的时候触发,最后用反射方法来赋值。所以到最后才能get到他的payload逻辑!

也就是说这条链子的逻辑大概是这个样子:

  1. 优先级列表进行排序,自定义了comparatorTransformingComparator

  2. templates进行排序的时候,它实际上在这里

    image.png

    1
    2
    调用的是
    InvokerTransformer.transform(templates)
  3. templates的iMethodNamenewTransFormer,因为templates 实例对象是 TemplatesImpl 类型的 , 实际上反射调用的是TemplatesImpl.newTransformer()方法

  4. 这个时候如果我们的恶意Class文件被怎么着实例化了,就能够触发恶意代码

image.png

最后将这个队列对象返回,进行序列化

调试

通过调试,我想知道以下几个问题

  1. 完整调用过程
  2. 上面的Class怎么被加载,导致恶意代码执行,因为TemplatesImpl.newTransformer()并不是终点。
  3. 触发队列排序的地方

在PriorityQueue的readObject方法处打上断点截断

image.png

通过遍历将序列化的数据读了出来,可以看到templates被读取了出来

image.png

步入heapify()方法

image.png

直接步入siftDown方法

image.png

步入siftDownUsingComparator方法,这里我们要用上自己定义的Comparator了!

image.png

步入compare方法

image.png

调用的就是InvokerTransformer.transform()

image.png

(多走了一步,红框处就是反射调用了newTransformer

TemplatesImpl.newTransformer,弹出计算器

所以我们必须要深究一下TemplatesImpl.newTransformer

image.png

TemplatesImpl.newTransformer

com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer

反射调用的方法,必须要在这里打断点才能截获

image.png

步入getTransletInstance()

这里需要_name不为空才能往下面走image.png

继续步入defineTransletClasses()

使用ClassLoader加载恶意字节码

image.png

且这里他的父类要是”com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet”,才能在下面实例化

加载完字节码之后,实例化,触发恶意方法,cc2结束

image.png

image.png