攻击原理与 Gadget 链
反序列化的危险不在于「还原数据」本身,而在于「还原过程自动触发的副作用」。
攻击链:反序列化攻击依赖一种称为「Gadget 链(Gadget Chain)」的技术模式。Gadget 是应用或其依赖库中存在的某个类中的一段代码——该代码在对象被反序列化、构造或销毁时自动执行,并且执行的操作可被攻击者间接控制。单个 Gadget 可能无害(如一个类在 __destruct() 中调用文件删除函数),但多个 Gadget 串联在一起——一个 Gadget 的输出成为下一个 Gadget 的输入——可以构成一条「从反序列化入口到命令执行」的完整执行路径。
Java 反序列化(最危险的原生机制):
Java 的 ObjectInputStream.readObject() 在反序列化一个对象时自动执行该对象所属类(及其所有父类和关联类)的 readObject()、readResolve() 和 finalize() 方法。如果攻击者能够控制反序列化的字节流,就可以构造一个「包含精心选择的一组嵌套对象」的字节流,这些对象按照预定的顺序触发 Gadget 链,最终调用 Runtime.exec() 执行任意系统命令。
Apache Commons Collections 3 和 4 中的 Transformer 接口(InvokerTransformer、ChainedTransformer 等)是历史上最著名的 Java Gadget 来源——Commons Collections 几乎被每一个 Java Web 应用间接依赖,而 Transformer 的设计(本意是将输入映射为输出)恰好提供了「反射调用任意方法」的能力。
由于 Java 反序列化攻击的危险性和普遍性,安全研究员 frohoff 和 gebl 在 2015 年发布开源工具 ysoserial——一个生成 30+ 条不同依赖库弹射链(Spring Framework、Groovy、Hibernate、Wicket、RMI 等)的 payload 生成器。同类工具包括 PHPGGC(PHP Gadget Chains Generator)和 ysoserial.net(.NET 反序列化 Gadget 生成器)。