Java反序列化之CommonsCollections(CC1)基础篇


前言

      本文包括:Java反序列化之CommonsCollections篇(CC1)的一些基础知识概念。


一、基本简介和环境

    1.Apache Commons Collections简介

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

    2.漏洞原理

      Apache Commons Collections 中提供了一个Transformer的类,这个接口的功能就是将一个对象转换为另外一个对象。
      然后整个利用链是需要重点关注这个类。

  • invokeTransformer:通过反射,返回一个对象。
  • ChainedTransformer:把transformer连接成一条链,对一个对象依次通过链条内的每一个transformer进行转换。
  • ConstantTransformer:把一个对象转化为常量,并返回。

    3.本文环境版本

      IDEA版本为:2021.1.3
      jdk版本为8u65,因为CC1的利用链在8u71的版本就修复了。下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
      Maven版本为:3.6.3,下载链接:https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/
      本文CommonsCollections的版本是3.2.1。3.1-3.21之间都可以。

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

      为方便调试需加入java源码,下载地址为:https://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/af660750b2f4。

    4.搭建过程

     1)下载openjdk对应版本的源码。并解压成文件夹。
在这里插入图片描述
在这里插入图片描述
     2)把jdk1.8.0_65文件夹中的src.zip解压。然后把下载的openjdk中的 jdk-af660750b2f4\src\share\classes的sun文件夹拷贝到解压的 src文件夹中。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
     3)IDEA创建maven项目,Project SDK选择你下载的jdk8u65的路径。然后下一步写你项目的名字和存放路径创建即可。
在这里插入图片描述
     4)创建好后,选择ProjectStructure项目结构。
在这里插入图片描述
     5)选择SDKs点击Sourcepath添加src最后应用保存即可。
在这里插入图片描述
     6)然后pom.xml文件中添加commons collections 3.2.1版本,直接下载资或者右键重新加载项目下载资源都可以。
在这里插入图片描述
在这里插入图片描述

二、基础学习

   1.命令执行的方式

     1)JAVA中正常的命令执行。

public class CC1 {
    public static void main(String[] atgs) throws Exception
    {
        // 1.先弹个计算器
        Runtime.getRuntime().exec("calc");
    }
}

在这里插入图片描述
     2)利用一个普通的反射执行命令。

import java.lang.reflect.Method;

public class CC1 {
    public static void main(String[] atgs) throws Exception
    {
//        // 1.先弹个计算器
//        Runtime.getRuntime().exec("calc");


        // 2.写一个普通的反射
        Runtime r = Runtime.getRuntime();
        // 获取Runtime的class
        Class c = Runtime.class;
        // 获取Runtime的exec方法
        Method execMethod = c.getMethod("exec",String.class);
        // 调用exec方法
        execMethod.invoke(r,"calc");
    }
}

在这里插入图片描述

   2.CC1链中涉及到的类的简介

     1)Transformer类是Commons Collections中自定义的一组功能类。Transformer类的功能就是接收一个对象然后调用transform方法,对这个对象做一些操作。

public interface Transformer {
    public Object transform(Object input);
}

     2)InvokerTransformer也是实现了Transformer接口的一个类,它可以执行任意的方法。在创建InvokerTransformer对象时,需要传入三个参数,第一个是想要执行的方法名,第二个是这个方法所需要参数的参数类型,第三个是这个方法中具体的参数;当调用InvokerTransformer类中的transform方法时,将会执行我们想要执行的方法,那具体是哪个对象中的方法呢?是通过transform方法中的参数传入进去的,接下来看看代码,首先是构造方法:

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
    super();
    iMethodName = methodName;
    iParamTypes = paramTypes;
    iArgs = args;
}

      就是将三个参数做一个赋值而已, 接下来就来看它的回调transform方法。

public Object transform(Object input) {
    if (input == null) {
        return null;
 }
 try {
     Class cls = input.getClass();
     Method method = cls.getMethod(iMethodName, iParamTypes);
     return method.invoke(input, iArgs);}
    catch (NoSuchMethodException ex) {
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' does not exist");} 
    catch (IllegalAccessException ex) {
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' cannot be accessed");} 
    catch (InvocationTargetException ex) {
        throw new FunctorException("InvokerTransformer: The method '" +iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);}
}

      这样它就可以执行input对象的iMethodName⽅法了,原理其实也挺简单,就是利用反射先获取这个方法,然后再执行input对象中的这个方法就行了
     3)TransformedMap这个类中封装了一个decorate方法,它是用来修饰Java中的标准数据结构Map,当向被修饰过的Map中添加新元素时,它就会执行一个回调函数;这个回调并不是传统意义上的回调函数,而是相当于执行一个对象里面的transform方法,前提是这个对象的类要实现了Transformer接口。参照下面代码可以看出来其中,keyTransformer是处理新元素的Key的回调,valueTransformer是处理新元素的value的回调,当我们向outerMap中添加新元素时,它就会调用keyTransformer或者valueTransformer里面的transform方法。

Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);

     4)ConstantTransformer同样是一个实现了Transformer接口的一个类,这个类很简单,它有一个带参的构造函数,而参数类型是对象,当你传入一个对象后,它会在transform方法中再将这个对象返回出来。就是将传入的对象constantToReturn在transform方法中返回

public ConstantTransformer(Object constantToReturn) {
    super();
    iConstant = constantToReturn;
}
public Object transform(Object input) {
    return iConstant;
}

     5)前面讲了ConstantTransformer和InvokerTransformer两个类,一个可以返回一个类的对象,另一个可以执行对象中的方法,那么我们是不是就可以尝试执行Runtime类中的exec方法呢?很显然,我们还需要一个类将这两个串起来,让ConstantTransformer类返回的对象,能作为参数,进入到InvokerTransformer类的transform方法中,这样就可以了,这时候就需要拿出我们的ChainedTransformer类了;ChainedTransformer类同样也是实现了Transformer接口的一个类,它就是将内部多个实现了Transformer接口的类串在了一起,并且将前一个回调函数transform返回的结果,作为后一个回调函数transform的参数传入,代码如下,挺简单的一个逻辑,就是不停的调transform

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;
}

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值