GCSA洞察:Fastjson 1.2.83 「Gadget-Free」 漏洞(0day)深度分析與防禦指南
金色財經
摘要
在傳統 Java 反序列化漏洞防禦體系中,業界普遍存在以下認知盲區:「AutoType 默認關閉就安全」、「固定了 parseObject 的第二參數(頂層目標類型)就安全」、「排空了本地 Classpath 的反序列化 Gadget 依賴就安全」。然而,最新的技術攻防演進徹底打破了這些僥倖心理。
GCSA全球網路安全聯盟今日獨家發布本篇技術洞察報告。 報告深入復盤了 Fastjson 1.2.83 在默認 AutoType=false 狀態下,依然可觸發無需傳統 Gadget 依賴的遠程代碼執行(RCE)的底層根因。目前,該利用技術已在 JDK 8 / 17 / 21 / 25 以及 Spring Boot Loader 隔離環境中端到端復現成功。本漏洞並非傳統的「繞過黑名單後尋找本地 Gadget」,而是直接將 Fastjson 自身的 Class 元數據探測邏輯扭轉為遠程惡意 Class 的獲取與授權通道。
以下為正文
發布機構: GCSA全球網路安全聯盟
報告類型: 獨家技術洞察 / 漏洞深度剖析報告
報告日期:2026-07-21
報告狀態:已完成源碼審計與隔離環境復現
漏洞編號:內部研究編號 FJ-GETRESOURCE-RCE(不對應已公開 CVE)
Fastjson 1.2.83 在默認 AutoType=false 下仍可觸發無需傳統 gadget 的遠程代碼執行,已在 JDK 8/17/21/25 + Spring Boot Loader 隔離環境復現。建議立即啟用 SafeMode 並遷移 Fastjson 2.x。
1. 執行摘要
Fastjson 1.2.83 的 ParserConfig.checkAutoType 會把用戶可控的 @type 值轉換為 class 資源名,並交給當前 ClassLoader 的 getResourceAsStream:
在能夠解析絕對 URL 資源名的 fat-jar ClassLoader 環境中,攻擊者可以利用點號替換 構造 http:、jar:http: 和 jar:file: URL,從攻擊端下載帶有 @JSONType 的 惡意 class。Fastjson 檢測到該註解後會調用 loadClass,並在危險基類檢查和目標類型 相容性檢查之前直接返回該 class。class 被實例化、初始化時即可執行任意代碼。
該利用不依賴目標 classpath 中已有的傳統反序列化 gadget,且在 Fastjson AutoType=false 的默認狀態下仍可觸發。固定 JSON.parseObject 的目標類型不能 阻止執行;啟用 SafeMode 可以在資源訪問前阻斷正常利用路徑。
本報告已使用同一個 JSON payload 在隔離 Linux 容器中完成以下復現:
| JDK | ClassLoader 環境 | Fastjson | 結果 |
| Temurin 8u492 | Spring Boot Loader 2.7.18 | 1.2.83 | RCE 成功 |
| Temurin 17.0.19 | Spring Boot Loader 3.2.0 | 1.2.83 | RCE 成功 |
| Temurin 21.0.11 | Spring Boot Loader 3.2.0 | 1.2.83 | RCE 成功 |
| Temurin 25.0.3 | Spring Boot Loader 3.2.0 | 1.2.83 | RCE 成功 |
2. 漏洞評級
| 項目 | 結論 |
| 漏洞類型 | 不安全反序列化 / 遠程 class 注入 / 遠程代碼執行 |
| 建議等級 | 高危;滿足已驗證部署條件時可按嚴重處理 |
| 攻擊向量 | 網路遠程 |
| 權限要求 | 無 |
| 用戶交互 | 無 |
| 機密性影響 | 高 |
| 完整性影響 | 高 |
| 可用性影響 | 高 |
| 利用複雜度 | 取決於 ClassLoader、出網能力及操作系統文件描述符接口 |
不建議僅憑組件版本給出統一的 CVSS 9.8:普通 AppClassLoader 是負對照,現代 JDK 完整鏈還依賴能夠解析兩種絕對 JAR URL 的 loader 和 /proc/self/fd。在滿足本報告 正向環境的應用中,漏洞效果為無需認證的網路 RCE。
3. 影響範圍與前置條件
3.1 已確認範圍
運行時確認:Fastjson 1.2.83。
JDK 確認:8、17、21、25。
操作系統確認:Linux;macOS 使用 /dev/fd 也完成了 JDK 17/21/25 復現。
loader 確認:
- Spring Boot 2.7.18 classic loader + JDK 8; - Spring Boot 3.2.0 loader + JDK 17/21/25。
API 確認:JSON.parse,以及固定頂層類型的 JSON.parseObject。
3.2 版本範圍說明
外部描述中的 1.2.68–1.2.83 更適合作為已知測試範圍,而不是漏洞引入版本。 源碼核對表明,決定性的 class 資源探測代碼在 1.2.67 和 1.2.68 中已經存在。本報告 僅對 1.2.83 完成了完整跨 JDK 運行時驗證,不能據此斷言更早版本全部具備完全相同的 端到端利用條件。
3.3 利用所需條件
攻擊者可以控制傳入 Fastjson 的 JSON,且輸入中的 @type 會被解析。
SafeMode 未啟用。
加載 Fastjson 的 ClassLoader 能把構造後的絕對資源名解析為 URL。
受害進程可以連接攻擊端 HTTP 服務。
現代 Linux 鏈要求 /proc/self/fd 可讀,並且 loader 能解析
jar:file:/proc/self/fd/N!...。
JDK 需要能夠創建正常的遠程 JAR 臨時緩存;這通常意味著 JVM 臨時目錄可寫。
攻擊者不需要:
向目標 classpath 寫入文件;
目標 classpath 預裝 TemplatesImpl、JNDI、C3P0、Commons Collections 等 gadget;
開啟 Fastjson AutoType;
控制 JSON.parseObject 的第二個參數。
4. 根因分析
4.1 用戶類型名被當作資源 URL
源碼位置:
核心代碼:
該邏輯假設 resource 只是普通 classpath 路徑,但沒有限制其協議、絕對路徑語義或 來源。對於特定 fat-jar loader,以下輸入會在替換後變成絕對 URL:
因此 getResourceAsStream 從本地元數據查詢越界為攻擊者可控的網路資源加載。
4.2 遠程 class 的 @JSONType 被當作授權依據
Fastjson 使用自己的 ASM ClassReader 解析資源內容:
攻擊端只需讓遠程 class 帶有 Fastjson 的 @JSONType 註解,即可將 jsonType 置為 true。這裡檢查的是攻擊者提供的字節,而不是一個已經由可信 classpath 加載的類。
4.3 jsonType 觸發實際類加載
源碼位置:
TypeUtils.loadClass 依次嘗試顯式 loader、線程上下文 loader 和 Class.forName。 在正向環境中,線程上下文 loader 會再次解析相同的絕對資源名、下載 class 並執行 defineClass。
4.4 @JSONType 早返迴繞過後續安全檢查
源碼位置:
因此,遠程 class 一旦攜帶 @JSONType:
危險基類檢查不會執行;
expectClass.isAssignableFrom(clazz) 不會執行;
固定數據綁定類型無法在 class 初始化之前阻止執行。
4.5 Exception/Error 後綴形成失敗軟通道
源碼位置:
現代 JDK 第一階段會因非法內部類名加載失敗。讓類型名以 Exception 結尾後, Fastjson 不會終止整個 JSON,而是返回 null,使解析器繼續處理數組中的 FD 枚舉 元素。這一分支是單 payload 跨階段執行的關鍵。
4.6 SafeMode 的位置
SafeMode 檢查位於資源訪問之前:
所以默認路徑中 SafeMode 能阻止網路請求。不過 AutoTypeCheckHandler 位於 SafeMode 之前(ParserConfig.java:1316-1323);如果應用主動註冊了一個直接返回 類型的 handler,需要單獨審計,不能把 SafeMode 理解為可覆蓋自定義 handler 的 絕對邊界。
5. 利用鏈詳解
5.1 JDK 8:直接遠程 class 加載
最短形式:
轉換鏈:
JDK 8 接受上述非常規內部類名。Spring Boot 2.7 的 LaunchedURLClassLoader 下載 class 後完成定義、實例化和初始化,惡意 執行命令。
JDK 17+ 同樣會完成網路請求,但拒絕內部名中的空路徑段:
所以短 http:.. 形式本身只在 JDK 8 完成 RCE。
5.2 現代 JDK 第一階段:下載遠程 JAR
單 payload 的首個數組元素:
轉換結果:
JDK 的 sun.net.www.protocol.jar.URLJarFile.retrieve 會創建 jar_cache* 臨時文件, 將遠程 JAR 複製到該文件,然後打開 JarFile。緩存仍由受害 JVM 持有;攻擊者不需要 知道隨機臨時文件名,也沒有直接向受害文件系統寫文件。
JDK 17+ 隨後拒絕第一階段 jar:http://... 內部名,但 Fastjson 因 Exception 後綴繼續解析數組。
5.3 現代 JDK 第二階段:重開緩存 FD
後續候選元素示例:
轉換鏈:
與 http:// 不同,該內部名的每個 / 分隔組件都非空,因此現代 JVM 接受。 攻擊 JAR 中為每個候選 FD 準備一個入口:
每個 class 的常量池內部名都與對應 FD 的請求類型精確匹配,並攜帶 @JSONType。 命中實際緩存句柄後,Fastjson 加載並實例化該類, 執行命令。
JDK 17 的 class-load 日誌中首個命中為:
5.4 為什麼一個 payload 同時兼容 JDK 8 和現代 JDK
JDK 8 直接接受第一階段 jar:http://... class 並執行。
第一階段 class 執行命令後故意拋出 RuntimeException("stage-one-stop"),阻止
JDK 8 繼續嘗試無關 socket/pipe FD。
JDK 17+ 在 class 初始化前就因第一階段非法名稱失敗,不會觸發該主動異常;隨後
通過 Exception 軟返回進入 FD 枚舉階段。
6. 復現環境與證據
6.1 被測構件哈希
6.2 一鍵復現
期望輸出:
腳本會:
編譯受害 fat jar;
生成帶 FD 專用 class 的攻擊 JAR;
生成一個 JSON 數組 payload;
在隔離 Docker 網路啟動攻擊端 HTTP 服務;
分別啟動 JDK 8/17/21/25 受害容器;
檢查每個容器映射出的 /tmp/fastjson-getresource-rce。
6.3 手工生成攻擊 JAR 和 payload
生成物:
--host 建議使用不含點號的 DNS 標籤或十進制 IPv4。原因不是繞過 localhost, 而是 Fastjson 會把類型名中的所有 . 都改成 /。例如十進制 IPv4 2130706433 等價於 127.0.0.1,但不會被點號替換拆開。
6.4 通過 Burp Suite 投遞
Burp 只負責向存在 Fastjson 解析點的受害接口發送 JSON;攻擊 JAR 仍需由攻擊端 HTTP 服務提供。
請求模板:
如果應用使用固定頂層類型,可根據字段結構包裝數組,例如:
本實驗使用 JSON.parseObject(json, BoundEnvelope.class) 解析上述包裝,結果仍為 RCE-OK,並正常返回 BoundEnvelope。
6.5 關鍵邊界測試
| 測試 | HTTP 請求 | 命令 marker | 結論 |
| AutoType=false | 有 | 有 | 關閉 AutoType 不足以防禦 |
| 固定 BoundEnvelope.class | 有 | 有 | 固定第二參數不足以防禦 |
| SafeMode=true | 0 | 無 | 正常默認 handler 環境下有效阻斷 |
| 普通 AppClassLoader | 0 | 無 | 不解析絕對遠程資源 |
| Boot 2.7 + JDK 17 | 首段有 | 無 | 第二段 jar:file:/proc/self/fd 未解析 |
| Boot 3.2 + JDK 17/21/25 | 有 | 有 | 完整現代鏈成立 |
7. 修復與緩解建議
7.1 首選:遷移出 Fastjson 1.x
優先遷移至維護中的 Fastjson 2.x,並重新驗證所有多態類型、AutoType 和兼容模式 配置。不要僅替換 JAR 而不做回歸測試。
7.2 立即啟用 SafeMode
代碼配置:
JVM 參數:
注意:應用如註冊了 AutoTypeCheckHandler,應同步審計或移除,因為 handler 在 SafeMode 檢查之前執行。
7.3 限制反序列化入口
不要把不可信請求直接交給 JSON.parse/JSON.parseObject。
在網關或應用入口拒絕任何形式的特殊類型元數據。
僅固定頂層 Java 類型不是充分防線,因為嵌套對象仍可處理 @type,且本漏洞的
jsonType 早返迴繞過相容性檢查。
7.4 WAF/網關臨時規則
臨時攔截 JSON key 解碼後等於 @type 的請求,並覆蓋 URL 參數、請求體及嵌套對象。 不能只搜尋明文 "@type",Fastjson lexer 會先解碼字段名,例如:
WAF 規則只能作為緩解,不能代替組件升級和 SafeMode。
7.5 出網與運行時加固
禁止業務 JVM 對非必要外部地址發起 HTTP/HTTPS 連接。
對應用容器實施最小網路策略。
在兼容性允許時限制 /proc/self/fd 暴露或使用更嚴格的容器沙箱。
審計 ClassLoader 對絕對 URL 資源名的處理,拒絕 http:、https:、jar:、
file: 等協議形式。
監控 JVM 臨時目錄中的異常 jar_cache* 活動。
8. 檢測建議與 IOC
8.1 請求側特徵
重點關註解碼後的 @type 值包含:
單獨出現 Exception 不足以告警,應與協議形式、@type 和數組內連續 FD 候選組合 關聯分析。
8.2 網路側特徵
JVM 向異常主機請求無擴展名 JAR 或 .class;
同一解析請求期間出現 1–3 次重複 GET/HEAD;
請求路徑中可能出現 /x、/a.class 或攻擊者自定義等價路徑。
8.3 主機側特徵
JVM 臨時目錄創建 jar_cache*;
Java 進程通過 /proc/self/fd/N 重新打開自身文件;
class-load 日誌出現類似:
9. 結論
本漏洞並非傳統的「繞過黑名單後尋找本地 gadget」,而是把 Fastjson 自身的 class 元數據探測邏輯變成了遠程 class 獲取和授權通道。@JSONType 早返回使攻擊者提供的 class 在危險基類和類型綁定檢查之前被接受;Exception 失敗軟通道及 JDK jar:http: 臨時緩存則將 JDK 8 的直接加載原語擴展到了 JDK 17/21/25。
因此以下常見判斷均不成立:
「AutoType 默認關閉,所以安全」;
「固定 parseObject 第二參數,所以安全」;
「classpath 沒有已知 gadget,所以安全」;
「JDK 17+ 會拒絕 http:// 內部名,所以最多隻是 SSRF」。
在滿足已驗證 loader、網路和文件描述符條件的部署中,該問題可以從單個未經認證的 JSON 請求發展為真實遠程代碼執行。應優先遷移 Fastjson 2.x,並立即啟用 SafeMode、 收緊出網與 ClassLoader 資源解析邊界。
10. 附件與證據路徑
⚠️ 轉載及版權聲明:本報告及相關技術分析由GCSA全球網路安全聯盟獨家發布。歡迎行業同仁、安全媒體進行學習與交流。如需轉載請務必完整保留GCSA官方出處及原始鏈接,並不得對報告核心觀點進行惡意篡改。感謝對網路安全生態共同維護的理解與支持!
來源:金色財經
發佈者對本文章的內容承擔全部責任
在投資加密貨幣前,請務必深入研究,理解相關風險,並謹慎評估自己的風險承受能力。不要因為短期高回報的誘惑而忽視潛在的重大損失。
暢行幣圈交易全攻略,專家駐群實戰交流
▌立即加入鉅亨買幣實戰交流 LINE 社群(點此入群)
不管是新手發問,還是老手交流,只要你想參與加密貨幣現貨交易、合約跟單、合約網格、量化交易、理財產品的投資,都歡迎入群討論學習!
- 讓加密貨幣幫你滾出年化30%現金流
- 掌握全球財經資訊點我下載APP
延伸閱讀
- 講座
- 公告
上一篇
下一篇