fastjson CVE-2026-16723:为什么 mvn dependency:tree 查不出你的漏洞

9 阅读5分钟

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-JARCVE-2026-16723 的主要在野利用场景
  结论  :命中 CVE-2026-16723CVSS 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/HIGH
  • 2 = 用法错误
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。 安全工具最怕的就是让人误以为安全,任何一条误判都值得提。