CommonsCollections2反序列化链分析
经过CC1和URLDNS两条链子的洗礼,从CC2开始打算自主调试分析
复现
依赖:commons-collections4-4.0.jar
分析
1 | /* |
Gadgets.createTemplatesImpl( )
跟进
这里稍有复杂,先一步一步分析
首先实例化了class com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
类
初始化ClassPool对象,插入ClassPath
通过ClassPool实例的.get()方法,获取CtClass对象
这个类作为基类,下面的操作都是基于此进行修改
为CtClass添加一个静态块,当这个类被实例化的时候,静态块内代码会执行,也就是我们传入的恶意命令
为这个类重新命名
获取到AbstTranslet类并将其设置为刚刚类的父类
添加一行输出,查看刚刚系一列操作最后得到的Class
这个时候就能很容易的把上面的各种Javassist的操作对应起来。Ysoserial用JAVAssist操作来动态修改了这个Class并且加入了一个会被自动加载的,存有恶意代码的静态块。
把字节码加载到实例对象里面,用Reflections.setFieldValue
设置成templates
域值
返回templates对象,方法结束
new InvokerTransformer( )
实例化InvokerTransformer
根据注释,这里只是模仿了method name,就是说还没有armed攻击载荷。
toString方法也不是想要反射调用的方法,只是占位。
关于InvokerTransformer
在CC1里面分析过了,这里不再赘述,其transform
方法可以反射调用,为CC的最根本的漏洞成因。
new PriorityQueue( )
新建一个优先级队列https://www.cainiaojc.com/java/java-priorityqueue.html
初始化的时候将新建的TransformingComparator
作为比较器传入
当我们跟进TransformingComparator
的时候,很清晰的能看到它的compare方法,调用了比较的两个对象的transform方法,这不就来了吗,初始化TransformingComparator
的时候,传入的transformer是InvokerTransformer
实例,这里调用的就是InvokerTransformer.transform
方法,实现反射调用
但是现在这个方法有点没头没尾的,哪里调用了compare,传入的两个参数又是啥,先看ysoserial怎么处理
Reflections.setFieldValue( )
之前占位的toString
被更改为newTransFormer
获取到了刚实例化的优先级字段的域值,进行修改
数组第一个元素变为刚刚包含了恶意字节码的templates对象,他就是上面用来compare
的object对象
这两个赋值操作让我一下豁然开朗啊!ysoserial就是这个模式,前面用占位符避免在payload生成的时候触发,最后用反射方法来赋值。所以到最后才能get到他的payload逻辑!
也就是说这条链子的逻辑大概是这个样子:
优先级列表进行排序,自定义了
comparator
为TransformingComparator
对
templates
进行排序的时候,它实际上在这里1
2调用的是
InvokerTransformer.transform(templates)templates的
iMethodName
为newTransFormer
,因为templates 实例对象是 TemplatesImpl 类型的 , 实际上反射调用的是TemplatesImpl.newTransformer()
方法这个时候如果我们的恶意Class文件被怎么着实例化了,就能够触发恶意代码
最后将这个队列对象返回,进行序列化
调试
通过调试,我想知道以下几个问题
- 完整调用过程
- 上面的Class怎么被加载,导致恶意代码执行,因为
TemplatesImpl.newTransformer()
并不是终点。 - 触发队列排序的地方
在PriorityQueue的readObject
方法处打上断点截断
通过遍历将序列化的数据读了出来,可以看到templates被读取了出来
步入heapify()方法
直接步入siftDown方法
步入siftDownUsingComparator方法,这里我们要用上自己定义的Comparator了!
步入compare方法
调用的就是InvokerTransformer.transform()
(多走了一步,红框处就是反射调用了newTransformer
即TemplatesImpl.newTransformer
,弹出计算器
所以我们必须要深究一下TemplatesImpl.newTransformer
TemplatesImpl.newTransformer
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer
反射调用的方法,必须要在这里打断点才能截获
步入getTransletInstance()
这里需要_name
不为空才能往下面走
继续步入defineTransletClasses()
使用ClassLoader加载恶意字节码
且这里他的父类要是”com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet”,才能在下面实例化
加载完字节码之后,实例化,触发恶意方法,cc2结束