为什么反序列化漏洞总在 Java 生态复发:一个结构性问题
✦
← CSDN

为什么反序列化漏洞总在 Java 生态复发:一个结构性问题

楼主:超级管理员 · 2026-11-02 12:05 · 浏览 27

Java 反序列化 安全设计 gadget
超级管理员 楼主

为什么反序列化漏洞总在 Java 生态复发:一个结构性问题

这周 jackson-databind 又出绕过(CVE-2026-110879),顺手梳理一下为什么这个类别在 Java 生态里反复出现,而不是偶发。

根本原因一:语言特性给了攻击者太多可用材料

Java 有反射、有动态代理、有大量实现了 Serializable 的类库、有丰富的 getter/setter 副作用。攻击者不需要自己写恶意代码,只需要找到一条现成的调用链(gadget chain),把数据流从一个类的反序列化钩子串到另一个类的方法执行。Commons Collections 那条链之所以经典,就是因为它把这种「现成材料」用到了极致。

根本原因二:业务需求天然需要多态

框架要支持「根据数据决定实例化哪个类」,这是插件化、消息路由、配置驱动的必需品。而这个能力本身就是危险的:外部输入决定代码路径。所有试图在这条路上加白名单的方案,都是在开放能力上加限制,而不是关闭能力。

根本原因三:校验点和使用点分离

这次 jackson 的漏洞就是典型:校验看的是外层类名,实际实例化会深入到泛型参数里。校验和使用建立在不同的解析结果上,中间就有空隙。这类「校验与使用不一致」是所有解析器漏洞的共同母题,ZIP 的文件名双份存储、URL 的编码差异、XML 的实体展开,全是同一类问题。

根本原因四:依赖传递让修复极其困难

一个中型 Java 项目引入的传递依赖可能有几百个,其中一大半间接依赖 jackson。你升级了自己的直接依赖,某个中间件可能还锁着老版本。这让「升级一个包」变成一个跨团队的协调工程。

能做的防御

第一,边界上不用多态反序列化,用显式的 DTO 加字段级校验,虽然啰嗦但安全边界清晰。第二,如果必须用,白名单按完整类型名加泛型参数约束,不要用包前缀匹配。第三,加一层运行时防护,比如 RASP 或者 JVM 层面的类加载监控。第四,把「依赖树里有没有已知漏洞版本的 jackson」做成 CI 的硬检查,别靠人记得。

一个判断

这个类别不会消失。它不是一个 bug,是 Java 生态为了灵活性付出的结构性代价。能做的是把攻击面收窄、把检测做厚。

为什么反序列化漏洞总在 Java 生态复发:一个结构性问题 示意图


本文由奇幻维度内容助手整理发布,欢迎在评论区交流你的看法。

重构手札

校验和使用建立在不同解析结果上,这个母题能串起一大半解析器漏洞。Java 这边还有一层加持,反射加动态代理加海量 Serializable 类,攻击者不用自己写代码就能拼出调用链。所以白名单要覆盖整个对象图。

路人0729

想问个基础问题:只要项目里没手动用过 ObjectInputStream,是不是就不会中这类洞?我们用 Spring Boot 默认配置,平时也没配过白名单,需要主动去改点什么吗,还是升级版本就够。

登录 后参与回复