2026 年 7 月 21 日,fastjson 公布了 CVE-2026-16723:CVSS 9.0,远程代码执行,默认配置即可利用——不需要开启 AutoType,不需要 classpath 上有特定 gadget,不需要认证。
影响范围是 fastjson 1.2.68 ~ 1.2.83。
这次和以往几次 AutoType 系列漏洞有个本质区别:
官方不会发布补丁。 fastjson 1.x 已经停止维护,GitHub 仓库已归档。
也就是说不存在"升个小版本就完事"这条路。要么迁移,要么长期带病运行。
公告后数日就出现了在野利用,主要目标是 Spring Boot fat-JAR 部署。
真正的难点不是修,是"找"
如果你的 pom.xml 里明明白白写着 fastjson,那这篇文章对你没什么用——你已经知道自己中招了,直接去迁移就行。
问题在于:大多数团队的 pom.xml 里根本没有 fastjson。
fastjson 极少被主动引入,它几乎都是传递依赖——被各种 SDK 捎带进来的。国内生态里尤其严重:支付、短信、对象存储、消息推送、地图、各种开放平台的 Java SDK,很多都在内部用 fastjson 做 JSON 序列化。
于是就出现了一个尴尬局面:
你没装它,但你在用它。而你不知道。
两个 mvn dependency:tree 的盲区
排查的第一反应当然是跑依赖树:
mvn dependency:tree | grep fastjson
这在大部分情况下够用。但有两种情况它无能为力,而这两种恰恰是应急场景里最常见的。
盲区一:你手上只有一个打好的 fat-JAR
线上应急的典型场景:运维扔给你一个 myapp.jar,没有源码,机器上没有 Maven,甚至没有网。
这时候 dependency:tree 是跑不了的——它需要构建环境和完整的 POM 依赖解析。
有人会说那就 unzip 出来看。可以,但 Spring Boot fat-JAR 的结构是 BOOT-INF/lib/*.jar,里面几十上百个 jar,还可能有嵌套。手工翻一遍的成本很高,而且容易漏。
盲区二:fastjson 被 shade 进了别的 jar 内部
这个更隐蔽。
有些 SDK 为了避免版本冲突,会在打包时用 maven-shade-plugin 把 fastjson 直接打进自己的 jar 里。结果就是:
- 依赖树上完全没有 fastjson 这个节点
- 但目标 jar 内部实实在在有
com/alibaba/fastjson/JSON.class - 这段代码会被正常加载、正常执行、正常受漏洞影响
我一开始也以为依赖树干净就等于没事。实际上依赖树干净只说明没有独立的 fastjson 依赖节点,不说明 classpath 上没有 fastjson 的字节码。
能被 JVM 加载的类,才是攻击面。依赖树只是它的一个不完整投影。
写了个工具专门查这两种情况
针对上面两个盲区写了个小工具,fastjson-check:
# 扫一个 jar,Spring Boot fat-JAR 会自动逐层展开
java -jar fastjson-check.jar ./myapp.jar
# 扫一整个目录,递归找所有 jar/war
java -jar fastjson-check.jar /opt/apps
# 输出 JSON,接流水线
java -jar fastjson-check.jar /opt/apps --json
输出长这样:
fastjson-check 0.1.0 —— fastjson 应急排查(离线,不外传任何数据)
扫描目标:myapp.jar
已展开归档:3 个
发现 2 处 fastjson:
[CRITICAL] fastjson 1.2.83
位置 :myapp.jar!/BOOT-INF/lib/fastjson-1.2.83.jar
版本来源:pom.properties
场景 :Spring Boot fat-JAR ← CVE-2026-16723 的主要在野利用场景
结论 :命中 CVE-2026-16723(CVSS 9.0 远程代码执行),且官方无补丁
处置 :1.x 已停止维护,不会有修复版本。应急处置二选一:①(推荐)迁移至
fastjson2 2.0.63 或更高版本;② 无法立即迁移时,先启用 SafeMode
彻底关闭 AutoType 以缓解,但这不是长期方案。
[UNKNOWN] fastjson 版本未知
位置 :myapp.jar!/BOOT-INF/lib/some-sdk-3.1.0.jar
版本来源:未知
注意 :疑似被 shade 进宿主 jar(有 class 但无 Maven 元数据),
mvn dependency:tree 查不到它
结论 :无法确定 fastjson 版本
汇总:CRITICAL 1 UNKNOWN 1
注意第二条——那个 some-sdk-3.1.0.jar 把 fastjson 打进了自己内部,依赖树上完全看不见。这正是它存在的理由。
几个设计上的取舍:
- 零运行时依赖。 一个排查工具不该再往目标环境里塞任何东西,尤其不该塞 JSON 库——我们查的就是它。全程只用 JDK 自带的
java.util.zip。 - 编译目标 Java 8。 企业环境里大量 JRE 还是 8,打出来的 jar 要能直接丢到老机器上跑。
- 完全离线。 不联网、不上传任何数据。排查生产环境的包,把路径和依赖清单发到第三方服务器上是不可接受的。
- 内存内展开嵌套 jar。 不往磁盘落任何临时文件。
- 整个 jar 23KB。
一个容易踩的坑:迁到 fastjson2 ≠ 安全
官方给的迁移方向是 fastjson2。但要注意:
fastjson2 在 ≤ 2.0.62 时自身也有 RCE(多态反序列化,seeAlso 路径,同样是默认配置可触发)。
所以「我们已经迁到 fastjson2 了」这句话本身不构成安全结论,必须同时看版本号。安全版本是 2.0.63 及以上。
完整判定规则:
| 版本 | 判定 | 说明 |
|---|---|---|
| fastjson 1.2.68 ~ 1.2.83 | 🔴 CRITICAL | 命中 CVE-2026-16723,官方无补丁 |
| fastjson 1.x 其他版本 | 🟠 HIGH | 不中本次 CVE,但 1.x 已 EOL,有历史 AutoType RCE 系列漏洞 |
| fastjson2 ≤ 2.0.62 | 🔴 CRITICAL | 多态反序列化 RCE,默认配置即可触发 |
| fastjson2 ≥ 2.0.63 | 🟢 OK | 当前推荐版本 |
接 CI
退出码设计成可以直接做门禁:
0= 未发现需处理项1= 发现 CRITICAL/HIGH2= 用法错误
java -jar fastjson-check.jar ./build/libs || echo "发现高危依赖,阻断发布"
它不是什么
诚实说明边界,免得误以为安全:
- 它不是通用 SCA 工具。 只查 fastjson 一个库,不查其他 CVE。要全面的依赖安全扫描请用 Snyk / OWASP Dependency-Check / Dependency-Track。
- 改了包名的 relocate 打包检测不到。 它靠
com/alibaba/fastjson(2)/JSON.class这个路径识别;如果某个库在 shade 时把包名 relocate 成了com.foo.shaded.fastjson,就查不出来。 - 它不判断可达性。 发现依赖存在 ≠ 一定能被攻击,是否真的可利用取决于有没有外部可控的 JSON 输入路径。但在应急阶段,先把「有没有」查清楚是第一步。
- 它不改你的代码。 只报告,不动手。
地址
Apache 2.0,我写的。已经用 Maven 中央仓库的真实 fastjson 1.2.62 / 1.2.83 和 fastjson2 2.0.62 / 2.0.63 验证过,26 个单元测试。
发现误报或漏报请提 issue。 安全工具最怕的就是让人误以为安全,任何一条误判都值得提。