CC1-LazyMap
0x01 Preface
CC链的关键在于transform()的触发。 上一篇中transform()的触发点在AnnotationInvocationHandler的readObject调用了setValue,进而触发TransformedMap的checkSetValue,进而触发transform()
LazyMap是另一处触发点,LazyMap的get方法中会执行factory.transform()。顾名思义,''懒加载''只有当找不到值的时候才会去get
LazyMap:get元素时触发
TransformedMap:set元素时触发
public class LazyMap implements Serializable {
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
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);
}
}0x02 Step Forward
与TransformedMap不同,在sun.reflect.annotation.AnnotationInvocationHandler的readObject方法中并没有直接调用到Map的get方法。
ysoserial找到了AnnotationInvocationHandler的invoke方法中调用了get
sun.reflect.annotation.AnnotationInvocationHandler实际是个代理类,其实现了InvocationHandler接口。
📌目标:
readObject中调用任意方法,调用者是AnnotationInvocationHandler代理对象AnnotationInvocationHandler的invoke触发memberValues.get()因此代理对象的memberValues要设为LazyMapLazyMap#get触发factory.transform()
0x03 Weave POC
POC中触发invoke的是AnnotationInvocationHandler#readObject =>memberValues.entrySet()
因此Proxy.newProxyInstance传的是Map的ClassLoader和接口
0x04 Shortcomings
LazyMap的漏洞触发在get和invoke中 而TransformedMap的漏洞触发在setValue中 同样在 jdk 8u71之后,由于AnnotationInvocationHandler不再直接使用反序列化得到的Map对象,而是新建了一个LinkedHashMap对象,后续对Map的操作都是基于这个新的LinkedHashMap对象。 因此CC1链只局限在jdk 8u71之前的版本。
Last updated
Was this helpful?