CC7链分析
本文最后更新于:2024年10月14日 晚上
CC7链:Hashtable进行Trigger
直接打开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
6public 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
7protected 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 |
|
这里就需要用到hash碰撞的思想了,
- 对于一个给定的
和 ,难以找到一个 使得 ,这叫散列函数的弱碰撞性 - 对于一个散列算法
,难以找到 使得 ,这叫散列函数的强碰撞性
由于字符串是无限的,而hash值是有限的,出现碰撞是必然的,判断一个hash算法的好坏的其中一个重要因素就在于其抗碰撞的能力
这里不太清楚ysoseial-CC7
的作者是如何找到,yy和zZ会使得两个LazyMap
实例的hash值相同的。
不过不重要,直接拿来用,下面构造测试代码:
为什么要remove
,因为Hashtable
的put
方法也会触发LazyMap.get
导致lazyMap2中含有yy,使得在反序列化过程中,无法进入get
方法中含有transform
的部分,所有需要去除lazyMap2中的yy
1 |
|