CVE-2025-55182 是 ReactServer 中一個關鍵性的、無需驗證即可觸發的遠端程式碼執行漏洞,其 CVSS 分數為 10.0,屬於最高嚴重性等級。 作為OPSWAT 員計畫的一環,我們的研究員針對此漏洞進行了全面性的技術分析,深入探究其根源在於 React Flight 反序列化協定中的問題、完整的攻擊鏈,以及其對現代網路生態系統造成的廣泛影響。本部落格文章將呈現我們的研究發現,並為防禦者提供可執行的實務指引。

React 已成為全球採用最廣泛的前端函式庫之一,驅動了相當比例的現代網頁與mobile 。 Stack Overflow 的開發者調查始終將 React 列為頂尖的網頁框架之一,其採用率在全球專業開發者中已超過 40%。與此成長趨勢並行,React 團隊在 React 19 中推出了 ReactServer (RSC) 作為核心功能——這是一場範式轉移,將渲染邏輯從客戶端移至伺服器端,從而實現更優化的效能,並使伺服器端與客戶端程式碼之間能更緊密地整合。
然而,這種架構演進卻引入了一個關鍵的新攻擊面。2025 年 11 月 29 日,資安研究員 Lachlan Davidson 向 Meta 的漏洞懸賞計畫通報了 React 伺服器端反序列化邏輯中的一項漏洞。該漏洞於 2025 年 12 月 3 日以CVE-2025-55182 編號公開披露,可透過單一精心設計的 HTTP 請求,實現未經身份驗證的遠端程式碼執行。 此漏洞被歸類為 CWE-502(未受信任資料的反序列化),無需任何驗證、使用者互動或特殊應用程式設定——任何預設的「create-next-app」生產環境部署皆可立即遭到利用。

影響立竿見影且極為嚴重。在漏洞公開後的 48 小時內,便觀察到多起實際攻擊活動。根據 The Shadowserver Foundation 的資料,已有超過 77,000 個公開 IP 位址被確認可能存在漏洞。 Cloudflare 的遠程監測數據顯示,在漏洞披露後的一週內,記錄了超過 5.82 億次攻擊嘗試,攻擊強度平均每小時超過 3,500 個獨特來源 IP,並曾達到 16,585 個同時攻擊 IP 的峰值。Wiz Research 報告指出,39% 的雲端環境中存在受影響的實例。 美國網路安全與基礎設施安全局(CISA)已於 2025 年 12 月 5 日將此漏洞納入其「已知遭利用漏洞(KEV)」目錄。
威脅行為者的行動速度驚人且手法多樣。趨勢科技記錄了多起攻擊行動——包括「emerald」和「nuts」殭屍網路攻擊行動——這些行動部署了 Cobalt Strike 信標、Sliver 植入程式、Nezha 監控代理程式、Fast Reverse Proxy (FRP) 隧道,以及一種名為「Secret-Hunter」的新型有效載荷,該載荷將 TruffleHog 和 Gitleaks 等開源憑證竊取工具武器化。 GoogleThreat Intelligence 識別出數個與中國有關聯的威脅群組(UNC6600、UNC6586、UNC6588、UNC6603),這些群組部署了專用工具——包括 MINOCAT 隧道工具、SNOWLIGHT 下載器、COMPOOD 後門及 HISONIC 後門——並與伊朗相關的攻擊者及以財務為動機、進行加密貨幣挖礦活動的團體共同行動。 AWS 記錄顯示,早於 12 月 4 日,即完整概念驗證程式碼公開之前,與中國有關聯的團體便已開始測試漏洞利用程式碼。
關於 ReactServer
React 是一套用於建構使用者介面的 JavaScript 函式庫,由 Meta 及龐大的開源社群共同維護。 隨 React 19 推出的 ReactServer (RSC),標誌著 React 應用程式處理渲染方式的根本性轉變。與完全在瀏覽器中執行的傳統客戶端元件不同,伺服器元件在伺服器端執行,並產生 UI 的序列化表示形式,再將其串流傳送至客戶端。此設計可減少傳送至瀏覽器的 JavaScript 量、改善互動時間指標,並能直接存取資料庫和檔案系統等伺服器端資源。

RSC 仰賴一種名為「Flight」的自訂序列化協定,用於在客戶端與伺服器之間編碼及傳輸資料。當客戶端呼叫Server (前稱Server )時,瀏覽器會使用 Flight 格式,將函式參數封裝成結構化的 HTTP 請求。 伺服器會將此資料包反序列化,執行所請求的功能,並將結果串流傳回客戶端。這種客戶端與伺服器之間的緊密耦合(儘管在架構上相當優雅),意味著反序列化邏輯中的任何缺陷都可能造成立即且災難性的後果,正如 CVE-2025-55182 所示。
此漏洞不僅影響 React 本身,更波及所有基於 React 建構的框架生態系。 Next.js(該框架曾收到一則獨立的安全通報 CVE-2025-66478,後因重複而被駁回)、React Router、Waku、Parcel 的 RSC 外掛程式、Vite 的 RSC 外掛程式,以及 RedwoodSDK 均受到影響。即使應用程式未明確定義Server ,只要框架中啟用了 RSC 支援,也可能存在此漏洞。
技術背景
在探討此漏洞之前,需先了解支撐此攻擊鏈的三大基礎概念:JavaScript 針對 thenable 物件的 await 行為、原型鏈遍歷,以及 React Flight 協定的區塊式資料模型。
JavaScript 的 await 與 Thenable 物件
`await` 運算子會暫停非同步函式的執行,直到被等待的表達式解析完畢為止。當`await`遇到原生Promise 時,它會等待其完成並返回已解決的值。然而,`await` 並不要求必須是原生 Promise——任何具有`.then()`方法的物件(稱為「thenable」)都會被視為類似 Promise 的結構。
當 `await` 遇到一個 `thenable` 時,它會呼叫該物件的 `.then()` 方法,並傳入系統提供的 `resolve` 和 `reject` 回呼函式。傳遞給 `resolve` 的值將成為 `await` 表達式的結果。 關鍵在於,若解析出的值本身也是 thenable,則會遞迴呼叫該嵌套物件的 .then() 方法,直到遇到原始值或已解決的 Promise 為止。這種遞迴解析行為正是利用 CVE-2025-55182 漏洞的核心所在。
原型鏈遍歷
每個 JavaScript 物件都維持著與其原型的內部連結,可透過__proto__屬性存取。當存取物件上的某個屬性時,JavaScript 執行引擎會先檢查該物件自身的屬性。若未找到該屬性,引擎便會遍歷原型鏈——沿著每個__proto__連結向上追蹤——直到找到該屬性,或鏈條在 `undefined` 處終止為止。
攻擊者可利用此繼承機制,存取超出物件預期範圍的屬性。透過將 __proto__ 納入屬性存取路徑,攻擊者便能觸及應用程式從未打算公開的內部方法與建構函式。在 JavaScript 中,表達式 obj.__proto__.constructor.constructor 會返回全域的 Function 建構函式,該函式可根據字串輸入建立並執行任意函式。
React Flight 協定與基於區塊的資料模型
When a client invokes a Server Function, the browser sends an HTTP POST request with a multipart/form-data body. Each form field contains a numbered “chunk” of serialized data. The Flight protocol uses special string prefixes to encode data types: $<id> references the resolved value of another chunk, $@<id> references the raw chunk object itself, $W<id> represents a Set, $K<id> represents FormData, and $B<id> triggers the blob handler.
假設有一個定義如下所示的Server :

對應的 HTTP 請求包含多個表單欄位,每個欄位皆由一個鍵和一個值組成:欄位 0 包含參數陣列,其中包含如"$W1"和"$K2" 之類的參照,而欄位1和2_*則包含這些參照所解析出的資料。伺服器會在每個欄位送達時進行處理,並將中間結果儲存於稱為「區塊」的物件中。

一個區塊(chunk)是一個具有四項關鍵屬性的thenable 物件:status(解析狀態)、value(儲存的資料)、reason(錯誤資訊)以及 _response(對父級回應物件的回指)。 當伺服器遇到 await chunk 時,會呼叫該片段的.then()方法。若片段的狀態為 INITIALIZED,則 resolve 回呼函式會收到 chunk.value。若狀態為 PENDING、BLOCKED 或 CYCLIC,則回呼函式會被排入佇列以供稍後執行。

Chunk 0 通常代表被呼叫的Server 參數陣列。在接收所有表單欄位並解析所有內部參照後,chunk_0.value 會包含已完全組建的參數陣列,該陣列隨後會傳遞給目標函式。
端到端請求處理(Next.js → React Flight 反序列化)
以下內容將說明 Next.js 在正常情況下如何處理傳入的Server 請求,從 HTTP 層一直到 React Flight 反序列化引擎。

函式 handleAction() - Next.js
當Server 被呼叫時,請求會進入 handleAction 函式。此函式會驗證元資料、檢查標頭與 CSRF 憑證,並確認該請求為有效的擷取動作。 接著會建立一個名為busboyStream 的串流,用以解析多部分表單內容。decodeReplyFromBusboy函式會將事件發射器綁定至此串流,當接收到原始資料時,便會觸發 ReactServer反序列化處理函式。decodeReplyFromBusboy 的回傳值為chunk_0;await 運算子會解析該值,並將其組裝後的結果傳遞給被呼叫的Server 。

getChunk 函式會傳回對應於指定 ID 的區塊。若該區塊尚未存在,則會建立一個ResolvedModelChunk(若 response._formData 中已有資料)或一個 PendingChunk(若該 ID 尚未收到任何資料)。

當 decodeReplyFromBusboy 傳回 chunk_0 時,該區塊仍處於 PENDING 狀態。await 運算子會呼叫 chunk_0.then(),並將 resolve 和 reject 回呼函式暫時儲存於 chunk_0.value 和 chunk_0.reason 中。這些回呼函式會在參考解析完成後,由 wakeChunk 函式重新啟用。

反序列化流程 - ReactServer
當 busboyStream 接收完整的原始資料欄位時,它會觸發「field」事件發射器,呼叫 resolveField 函式,並啟動反序列化程序——將原始表單資料轉換為完整建構的 JavaScript 物件。以下函式負責管理此流程。
resolveField(response, key, value)

鍵值對會附加至 response._formData。接著,該函式會擷取與該鍵對應的 ID 所對應的區塊。若該區塊已存在,則會呼叫 resolveModelChunk 來重建它。這種延遲解析是必要的,因為值中可能包含對某些欄位的引用,而這些欄位的原始資料尚未送達;在此情況下,ReactServer 一個帶有自訂 resolve 和 reject 回呼函式的 PendingChunk,以便稍後處理這些引用。
resolveModelChunk(chunk, value, id)

resolveModelChunk 會建立一個狀態為 RESOLVED_MODEL 的 ResolvedModelChunk,並注入原始資料。接著,它會透過 initializeModelChunk 重建該區塊,並呼叫 wakeChunk 來觸發任何排入佇列的 resolve 和 reject 回呼函式,從而完成該物件或參照的解析。
initializeModelChunk(chunk)

initializeModelChunk 會將區塊的狀態轉換為 CYCLIC(表示正在進行參照解析),並開始進行反序列化。它會使用 JSON.parse 從 chunk.value 建立一個原始 JavaScript 物件,然後將此物件傳入 reviveModel 函式中。
reviveModel(response, parentObj, parentKey, value, reference)

reviveModel 會遞迴處理已解析物件中的每個元件。當遇到字串值時,它會呼叫 parseModelString 來處理該值。
parseModelString(response, obj, key, value, reference)

parseModelString 會根據字串前綴進行分派,以處理不同編碼類型的參考。對於以 $ 開頭的參考,會呼叫 getOutlinedModel 函式來解析跨區塊參考。
getOutlinedModel(response, reference, parentObject, key, map)

getOutlinedModel 會根據「:」分隔符號將參照拆分為屬性存取路徑,然後在目標區塊物件上遍歷該路徑,以返回被參照的值。如下文「漏洞分析」所述,正因這些屬性名稱未經驗證,才正是漏洞存在的關鍵所在。
漏洞分析
根本原因
CVE-2025-55182 originates from insufficient input validation in the getOutlinedModel() function within React’s server-side Flight reply handler (ReactFlightReplyServer.js). When a chunk reference includes a property path - such as $<id>:<prop1>:<prop2> - the function resolves it by traversing the specified properties on the target chunk object, computing the result as chunk[prop1][prop2].

關鍵的漏洞在於,這些屬性名稱從未經過驗證。 伺服器並未驗證所請求的屬性究竟是物件本身的屬性,還是繼承自原型的屬性。因此,攻擊者可以在屬性路徑中加入`__proto__`,藉此遍歷原型鏈,並存取那些本不應透過使用者控制的輸入來存取的內部方法。例如,參考 `$1:__proto__:then` 會解析為 `Chunk.prototype.then` —— 攻擊者隨後便能使用受控的參數來呼叫此函式。

易受攻擊的代碼
此漏洞利用鏈利用了 React 的 Flight 反序列化邏輯中兩條不同的程式碼路徑。
首先是 Chunk.prototype.then,它決定了區塊作為 thenable 時的行为。當 await 應用於處於 INITIALIZED 狀態的區塊時,系統會呼叫 resolve(chunk.value)。如果 chunk.value 本身是一個 thenable(即具有.then()方法的物件),則 await 運算子會遞迴地呼叫 chunk.value.then()。這種遞迴解析機制,正是攻擊者藉此將執行流程重定向至任意函式的途徑。
第二個是 parseModelString() 中的 $B(blob)前綴處理器:

在 $B 案例中,該函式會呼叫 response._formData.get(response._prefix + id)。_formData.get 和 _prefix 皆為儲存於區塊內的 _response 物件之屬性。透過遍歷原型鏈來操控這些屬性,攻擊者便能將此呼叫重定向,使其以任意程式碼作為參數來呼叫全域的 Function 建構函式。
開發
Through prototype chain traversal, an attacker reaches the global Function constructor via the path <any_object>.constructor.constructor. Because Chunk.prototype.then is a function, the path $1:constructor:constructor resolves to the global Function constructor, which accepts a string and returns a callable function containing that code.

為了展示其潛在的實際影響,我們的研究員根據多個資安研究團隊獨立記錄的分析結果,建構了一個概念驗證型載荷。此漏洞利用程式分為兩個階段運作:
第一階段——建構虛構片段:
The object delivered in field 0 acts as a fake chunk. Its then property is set to Chunk.prototype.then via the reference path $1:__proto__:then, allowing the Flight deserialization engine to invoke prototype-level behavior on this attacker-constructed object. The _response._formData.get property is pointed at the global Function constructor via $1:constructor:constructor, and _response._prefix is set to the malicious JavaScript code. The value field contains the string {"then": "$B0"}, instructing the blob handler to invoke itself on the same chunk when resolved. The status field is set to resolved_model so that initializeModelChunk is triggered when .then() is called, causing value to be parsed and the blob handler to fire.
由於此時尚未收到字段 1,ReactServer 會Server 建立 resolve 和 reject 回調函式,以處理此待處理的引用。
第二階段——觸發因素的解決:
一旦字段 1(包含 "$@0",即對第 0 個區塊的原始引用)被傳遞,待處理的區塊便會解析並直接指向該偽區塊。這會觸發 wakeChunk,該方法會在引用解析過程中處理排隊的回呼函式,並啟動原型鏈遍歷。 一旦偽塊完全解析完成,wakeChunk 便會再次被呼叫。由於偽塊的解析回呼函式是 Node.js 的隱含解析函式,它會呼叫該塊的 .then() 方法並解析其值——最終透過 Function 建構子來建構並執行注入的惡意程式碼。
完整的漏洞利用僅需一個 HTTP 請求:

Replacing {{COMMAND}} with any JavaScript code executes it on the server. The reason: -1 field prevents a toString() error during processing. The Next-Action header may contain any arbitrary value - even x - because the vulnerable deserialization occurs before the server validates the requested Server Function. This is what makes the vulnerability pre-authentication: the payload is processed during the deserialization phase, before any application-level authentication or authorization logic is reached.
一旦攻擊成功,攻擊者將在伺服器上獲得完整的 Node.js 執行環境,包括可存取 `child_process` 來執行 shell 指令、包含資料庫憑證與API 環境變數、本地檔案系統,以及能進行橫向移動的雲端元資料端點。
概念驗證
我們的研究人員在受控的實驗室環境中,利用透過 create-next-app 生成並針對生產環境建置的標準 Next.js 應用程式,成功重現了此漏洞——且未對預設設定進行任何修改。此次重現證實,上述所述的單次請求攻擊載荷確實能可靠地實現遠端程式碼執行。


受控演示顯示,若攻擊者能透過網路存取存在漏洞的 Next.js 伺服器,即可執行任意的 Node.js 程式碼——包括透過 child_process.exec() 建立反向殼層、讀取環境變數,以及存取本地檔案系統——且無需提供任何憑證,亦不會觸發任何應用程式層級的驗證檢查。 Next-Action 標頭接受任意值這一點,進一步證實了此漏洞屬於「認證前」漏洞:伺服器會在執行任何動作查詢或授權檢查之前,先處理並反序列化載荷。
解決之道
React 團隊於 2025 年 12 月 3 日發布了修補程式,這一天正是該漏洞公開披露之日。已修復的版本包括 React 19.0.1、19.1.2 及 19.2.1。 此修補程式在 getOutlinedModel() 和 reviveModel() 中新增了嚴格的屬性驗證機制,明確阻止從 Flight 有效載荷中由使用者控制的參照路徑解析繼承的原型屬性——包括 __proto__、constructor 和 prototype。
各組織應立即採取以下行動:
- 請根據實際情況執行 `npm install react-server-dom-webpack@latest`、`react-server-dom-parcel@latest` 或 `react-server-dom-turbopack@latest`,將 React 套件升級至修補版本(19.0.1、19.1.2 或 19.2.1)。
- 升級框架依賴項— Next.js、React Router、Waku 及其他受影響的框架均已發布相應的修補程式。請參閱 React 團隊的公告,以了解各版本的具體升級路徑。
- 請勿僅依賴主機服務供應商的緩解措施——雖然 Vercel 等供應商在漏洞曝光後部署了臨時性的 WAF 規則,但這些僅是權宜之計,無法取代對底層套件進行修補。
- 檢查伺服器日誌中是否存在帶有 Next-Action 標頭、且內容為 multipart/form-data 格式並包含 $@ 或 __proto__ 模式的 POST 請求,並監控應用程式日誌中是否出現意外的 child_process 或 execSync 呼叫。
透過OPSWAT進行風險緩解
OPSWAT 是 MetaDefender™ 平台內的一項專有技術,能提供抵禦 CVE-2025-55182 等漏洞所需的可視性與控制能力。 由於此漏洞存在於開源 npm 套件(react-server-dom-webpack、react-server-dom-parcel、react-server-dom-turbopack)中,企業必須先建立完整的清單,掌握這些元件在基礎架構中的部署位置,才能進行有效的修復。

OPSWAT 會生成一份完整的清單,列出所有正在使用的軟體元件、函式庫、容器及依賴項。當掃描包含易受攻擊 React 套件的應用程式或容器映像時,系統會自動將 CVE-2025-55182 標記為「嚴重」級別,並提供可用修補版本的指引,讓資安團隊能在漏洞遭利用前,優先處理並進行修復。
OPSWAT 同時內建於MetaDefender (用於掃描個別應用程式和容器映像)以及MetaDefender Software Chain™(用於提供整個開發生命週期中的管道層級可視性)。兩者結合,可協助資安團隊:
- 快速定位存在安全漏洞的組件——立即識別哪些應用程式和容器包含受影響的 react-server-dom-* 套件(版本存在安全漏洞),確保沒有任何部署被遺漏。
- 確保主動修補漏洞——持續監控開源依賴項,以便在發布新安全通報時,及時偵測過時或存在安全風險的套件,從而縮短系統暴露於風險中的時間。
- 維持合規性與供應鏈透明度——透過建立所有軟體元件及其已知漏洞的可稽核紀錄,以符合法規要求。
CVE-2025-55182 漏洞被利用的速度與規模——僅首週就出現超過 5.82 億次攻擊嘗試——充分說明了為何被動修補已不再足夠。了解您擁有哪些軟體、它們在何處運行,以及何時會出現漏洞,是主動防禦的基礎。而這種可視性,始於軟體成分清單(SBOM)。
引用
- React 團隊 - ReactServer 中的重大安全漏洞
- Wiz Research - React2Shell (CVE-2025-55182):React 嚴重漏洞
- 趨勢科技 - CVE-2025-55182:React2Shell 分析、概念驗證混亂,以及實際環境中的攻擊利用
- Akamai - CVE-2025-55182:React 和 Next.jsServer 遠端程式碼執行漏洞
- GoogleCloud 多個威脅行為者利用 React2Shell 漏洞 (CVE-2025-55182)
- AWS - 中國與 Nexus 網路威脅組織正迅速利用 React2Shell 漏洞
- NVD - CVE-2025-55182
- 理解 ReactServer - Tony Alicea
- MDN Web Docs - await 運算子
- React 原始碼 - ReactFlightReplyServer.js (v19.0.0)
- Next.js 原始碼 - action-handler.ts (v16.0.0)
