CommonsCollections2

CommonsCollections2

摘要:CC2

0x01 链子

这条链子对应的是commons-collections:4.0

这条链子的原理是通过PQ中的heapify方法里会调用自己的Transformer进行比较导致的字节码执行。

一些疑问

为什么要有CC2:CC2主要是用于处理CC1在高版本jdk中无法使用的问题,以及4.0包中链子的问题;

为什么只有在commons-collections:4.0可用:在P神的Java安全漫谈16中有提到,这条链子无法在4.0+和3.x版本中使用,原因是利用链中的org.apache.commons.collections4.comparators.TransformingComparator 并未实现Serializable接口;而从4.1起,官方直接禁用了InvokerTransformer等类的使用。用P神的话讲,更绝

调试

1、直接跳过ObjectInputStream#readObject(),来到PriorityQueue#readObject();

2、进入到heapify();

CC21

3、跳过一些包装直接进入到siftDownUsingComparator(),关注到第722行comparator.compare();

CC22

4、进入到一开始PoC中设置的comparator:TransformingComparator的compare方法,到此链子调试完毕,此处触发TemplateImp字节码任意执行命令的链子。

CC23

0x02 ysoserial源码分析

同之前一样,CC2这条链子也使用了自己定义的方法来生成荷载。这次使用的是createTemplatesImpl,传入了三个参数:

第一个参数为TemplatesImpl类,用于生成TemplatesImpl实例
第二个参数为AbstractTranslet
第三个参数为TransformerFactoryImpl类,为TemplatesImpl实例中_tfactory属性需要的值

而构造TemplatesImpl利用链的要点在于:

  • _bytecodes为字节码,字节码中对应的类必须为AbstractTranslet的子类

  • _name为任何字符串但不可为空

  • _tfactory得是TranformerFactoryImpl对象。而ysoserial也是按照这个套路来行事的。

来看一些初看会非常迷惑的点:

1、静态代码块的设置

1
2
3
4
String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
"\");";
clazz.makeClassInitializer().insertAfter(cmd);

这里是往StubTransletPayload类中加入静态代码块,包含执行代码cmd。这个静态代码块可以参考P神的Java安全漫谈系列反射那一节的文章。

2、为什么是AbstractTranslet

源码往下一点有这样一句代码:

1
2
CtClass superC = pool.get(abstTranslet.getName());
clazz.setSuperclass(superC);

这里将clazz(也就是恶意类)的父类设置为AbstractTranslet,之所以如此,看TemplatesImpl的调用链:

1
2
3
4
5
6
TemplatesImpl.getOutputProperties()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
ClassLoader.defineClass()
Class.newInstance()

来到TemplatesImpl第415行,这里处于defineTransletClasses()方法内部:

CC24

这里会将字节码中的类的父类整出来,而后在getTransletInstance()中的455行:

CC25

实例化这个类,而后触发static代码块。


评论