cc7的思路同样是找了另一条调用链来触发Lazy.get方法

Hashtable类

在ysoserial中给出的调用链中,选取了java.util.Hashtable.readObject方法作为反序列化的起点

Untitled

Hashtable提供put方法,这里的key和value为手动put进的键值对

java.util.Hashtable.readObject方法会调用reconstitutionPut方法,参数key,value可控,跟进reconstitutionPut方法,截取关键部分

Untitled

当e不为null时,会进入for语句。for语句中有一个if语句,可触发e.hash和e.key.equals方法

在java.util.Hashtable.readObject方法有个for循环语句,以Hashtable中的键值对来循环次数。每次循环会执行reconstitutionPut方法,将上一次的键值对信息写进tab中

Untitled

所以要执行两次put语句,才能保证tab不为空

Java语言还存在一个布尔短路运输的特性,也就是说当e.hash == hash判定为假,就会直接退出if语句,导致不执行e.key.equals(key)

ysoserial这里设置e.key为LazyMap对象,由于LazyMap下没有equals方法,所以它会调用父类AbstractMapDecorator.equals方法

Untitled

还会调用this.map.equals(object)方法

判断this.map:

想要执行transformer的transform方法,那么需要用Lazy.decorate方法对transformerChain进行修饰

Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerChain);

还需要将这个outerMap用put存进Hashtable,以达到e.key为LazyMap对象的目的

Hashtable table = new Hashtable();
table.put(outerMap, 1);