
CVE-2025-55182(React2Shell)RSC Flight デシリアライゼーション RCE のアドバイザリと分析。根本原因の分解、攻撃フロー、パッチ差分、Sigma/Suricata/WAF 検出ルールを収録。
最終確認日: 2026-11-04 (KST)。各数値は下部 References の出典で確認した値のみを記載しており、出典間で値が異なる場合はすべて併記しました。
Function コンストラクタまで到達し、任意の JavaScript を実行できる可能性があります。react-server-dom-webpack / -parcel / -turbopack 19.0.0、19.1.0、19.1.1、19.2.0 と、これを使用するフレームワーク — 代表例として Next.js 15.x / 16.x App Router。Server Function を直接定義していなくても、RSC をサポートしていれば影響を受けます。| 項目 | 内容 |
|---|---|
| CVE ID | CVE-2025-55182 (React) / Next.js 用の CVE-2025-66478 は**重複として拒否(Rejected)**された |
| 別名 | React2Shell |
| 公開日 | 2025-12-03 (React チームの勧告、同日にパッチ配布) |
| 発見者 | Lachlan Davidson (2025-11-29 に Meta Bug Bounty で報告) |
| 影響製品/バージョン | react-server-dom-webpack、react-server-dom-parcel、react-server-dom-turbopack 19.0.0、19.1.0、19.1.1、19.2.0 / Next.js 14.3.0-canary.77 以降の canary、15.x、16.x (App Router) |
| パッチバージョン | RCE 修正: React 19.0.1 / 19.1.2 / 19.2.1、Next.js 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 推奨最終バージョン(後続の脆弱性を含む): React 19.0.3 / 19.1.4 / 19.2.3 (下記「後続の脆弱性」を参照) |
| CVSS v3.1 | 10.0 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CVSS v4.0 | 本ドキュメント作成時点で一次情報源からは確認できず |
| CWE | CWE-502 Deserialization of Untrusted Data (Vercel GHSA-9qr9-h5gf-34mp、GitLab Advisory DB)。CISA KEV の項目には CWE の記載なし |
| 実際の悪用状況 | 悪用を確認。 CISA KEV 登録 2025-12-05、連邦機関の対応期限 2025-12-12、ランサムウェアキャンペーンでの使用: Known。AWS は公開から数時間以内に悪用の試行を観測 |
| 構成要素 | 影響バージョン | 修正バージョン |
|---|---|---|
react-server-dom-webpack / -parcel / -turbopack | 19.0.0 | 19.0.1 (推奨 19.0.3) |
| 〃 | 19.1.0, 19.1.1 | 19.1.2 (推奨 19.1.4) |
| 〃 | 19.2.0 | 19.2.1 (推奨 19.2.3) |
| Next.js 15.x (App Router) | 15.0 ~ 15.5 パッチ以前 | 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 |
| Next.js 16.x (App Router) | 16.0.7 未満 | 16.0.7 |
| Next.js canary | 14.3.0-canary.77 以上 | 15.6.0-canary.58 / 16.1.0-canary.12 (14.3 canary 利用者は 14.x stable へダウングレード) |
| その他の RSC 統合ツール | React Router(unstable RSC API)、Waku、Parcel RSC プラグイン、Vite RSC プラグイン(@vitejs/plugin-rsc)、RedwoodSDK、Expo など | 各ツールの最新バージョン + パッチ済み react-server-dom-* |
影響なし: サーバーを使用しない純粋なクライアント React アプリ、Next.js 13.x / 14.x stable、Pages Router アプリ、Edge Runtime デプロイ。
React2Shell のパッチ以降、RSC に関する追加研究により RCE ではない脆弱性が相次いで公開されました。RCE 自体は 19.0.1 / 19.1.2 / 19.2.1 で修正されましたが、以下の脆弱性まで防ぐには最新バージョンが必要です。
| CVE | 種類 | CVSS v3.1 | 公開 | 修正バージョン |
|---|---|---|---|---|
| CVE-2025-55184 | サービス拒否(DoS) | 7.5 | 2025-12-11 | 19.0.2 / 19.1.3 / 19.2.2 (不完全) |
| CVE-2025-55183 | ソースコード露出 | 5.3 | 2025-12-11 | 19.0.2 / 19.1.3 / 19.2.2 |
| CVE-2025-67779 | CVE-2025-55184の不完全なパッチによるDoS | 7.5 | 2025-12-12 | 19.0.3 / 19.1.4 / 19.2.3 |
一部のセキュリティベンダーの記事(例: Zscalerのアップデート)は「CVE-2025-55182の元のパッチは不完全だった」と表現しています。しかしReact・GitLabの勧告に基づくと、不完全だったのは**DoS修正(CVE-2025-55184)**であり、RCE修正がバイパスされたという一次情報源は確認できませんでした。いずれにせよ推奨される対応は19.0.3 / 19.1.4 / 19.2.3以上です。
| 日付 | 出来事 |
|---|---|
| 2025-11-29 | Lachlan DavidsonがMeta Bug Bountyで報告 |
| 2025-11-30 | Metaのセキュリティ研究者が確認、Reactチームと修正に着手 |
| 2025-12-03 | Reactの勧告およびパッチ(19.0.1 / 19.1.2 / 19.2.1)、Next.jsの勧告(CVE-2025-66478)を公開。クラウド・WAFベンダーは事前共有を受け保護ルールを配布 |
| 2025-12-03 ~ 04 | AWS、公開から数時間以内に中国系グループ(Earth Lamia、Jackpot Panda)による悪用の試みを観測。Zscalerは最初の2時間で4,100件以上の悪用の試みを観測 |
| 2025-12-05 | CISA KEVに登録(期限12-12)。Microsoftはこの日から実際の悪用活動を検知 |
| 2025-12-11 | 後続の脆弱性CVE-2025-55184 / 55183を公開 |
| 2025-12-12 | CVE-2025-67779(不完全なパッチ)を公開、19.0.3 / 19.1.4 / 19.2.3を配布 |
| 2025-12-15 | Microsoft、悪用後の活動分析およびハンティングガイドを公開 |
RSCはクライアント・サーバー間のデータをFlightという独自のシリアライズプロトコルでやり取りします。クライアントがServer Functionを呼び出すと、ブラウザは引数をmultipart/form-data POSTリクエストとして送信し、各フォームフィールドは番号が付いたチャンク1つになります。
$<id>は別のチャンクの値参照、$@<id>はチャンクオブジェクト自体の参照、$B<id>はBlob処理。then()メソッドを持つthenableオブジェクトです。JavaScriptのawaitはthenableに出会うとthen()を呼び出し、結果がまたthenableであれば再帰的に呼び出し続けます。getOutlinedModel()の無検証なプロパティ探索サーバー側のFlightレスポンス処理器(packages/react-server/src/ReactFlightReplyServer.js)のgetOutlinedModel()は、$<id>:<prop1>:<prop2>形式の参照を:で分割し、対象チャンクでchunk[prop1][prop2]の順にプロパティをたどります。
このとき、プロパティ名がオブジェクト自身のプロパティ(own property)であるかを検証していませんでした。 そのため、__proto__、constructor、prototypeのような名前で継承されたプロパティにまでアクセスできました。
JavaScriptでは任意のオブジェクトのconstructor.constructorはグローバルの**Functionコンストラクタ**であり、文字列を受け取って実行可能な関数を生成します。公開分析(OPSWAT、Zscaler)によると、攻撃者は次の2つを組み合わせます。
| 要素 | 悪用方法 (概念) |
|---|---|
| プロトタイプ探索 | 参照パスで内部メソッド(Chunk.prototype.then)とFunctionコンストラクタにアクセス |
then()の再帰的解釈 | 攻撃者が構成した偽のチャンクがthenableとして扱われ、逆シリアライズエンジンがその状態をそのまま信頼 |
$B(Blob)処理器 | 内部レスポンスオブジェクトのメソッド呼び出し経路を横取りし、Functionコンストラクタに攻撃者コードを渡すよう誘導 |
Next.jsでは、Server FunctionリクエストはhandleAction()を経てReactのFlight逆シリアライズに渡されます。逆シリアライズは、どのServer Functionを呼び出すかを確認する前に実行されます。そのため、Next-Actionヘッダーの値が実際に存在するアクションでなくても、ログインの背後にあるエンドポイントであってもペイロードが処理されます(OPSWAT)。デフォルトのcreate-next-appプロダクションビルドも、特別な設定なしで影響を受けます。
コードが実行されると、Node.js実行コンテキスト全体 — child_processを介したシェルコマンド、環境変数(DB資格情報・APIキー)、ローカルファイルシステム、クラウドメタデータエンドポイント — にアクセスできます。
以下は、公開分析(Zscaler、OPSWAT、Seqrite)の記述に基づいて変更の要点を再構成した概念コードです。実際のコミットの原文ではなく、関数シグネチャなどの詳細は推測です。正確なdiffは
facebook/reactの19.0.1 / 19.1.2 / 19.2.1リリースの変更分で確認してください。(修正コミットのハッシュは、本文書作成時点で一次ソースとして確認できませんでした。)
Before (脆弱)
// ReactFlightReplyServer.js — getOutlinedModel (개념)
function getOutlinedModel(response, reference, parentObject, key, map) {
const path = reference.split(':');
const id = parseInt(path[0], 16);
const chunk = getChunk(response, id);
// ...
let value = chunk.value;
for (let i = 1; i < path.length; i++) {
value = value[path[i]]; // __proto__, constructor 등 상속 속성까지 그대로 탐색
}
return map(response, value);
}
After(パッチ)
// 자신의 속성(own property)만 허용 (개념)
const hasOwnProperty = Object.prototype.hasOwnProperty;
function getOutlinedModel(response, reference, parentObject, key, map) {
// ...
for (let i = 1; i < path.length; i++) {
const name = path[i];
if (!hasOwnProperty.call(value, name)) {
// 상속된 속성 접근 차단 → 역직렬화 실패 처리
throw new Error('Invalid reference.');
}
value = value[name];
}
// ...
}
// 모듈 export를 해석하는 경로(requireModule 등)에도 동일한 own-property 검사 추가
| 区分 | Before | After |
|---|---|---|
| 参照パス属性の探索 | プロトタイプチェーンを含むすべての属性 | 自身の属性のみ (hasOwnProperty.call()) |
| モジュール export の解決 | 継承属性まで返却可能 | own-property 検査後に返却 |
__proto__ / constructor / prototype | アクセス可能 | ブロック |
| 結果 | Function コンストラクタに到達 → RCE | 参照解決失敗 |
Smashing Magazine の分析によると、パッチは hasOwnProperty 参照を事前にキャッシュしておき、逆シリアル化経路のすべての属性検査で .call() を介して呼び出します。これは、攻撃者が対象オブジェクトの hasOwnProperty 自体を上書きして検査を回避することを防ぐ一般的な防御パターンです(意図に関する解釈は推測)。
| 条件 | 内容 |
|---|---|
| 認証 | 不要 — 逆シリアル化がアクション確認・認証より先に実行される |
| ユーザー操作 | 不要 |
| ネットワーク位置 | リモート。RSC サーバーエンドポイントに HTTP リクエストを送信できればよい |
| 対象条件 | 脆弱なバージョンの react-server-dom-* を使用する RSC サーバー。Server Function を定義していなくても RSC サポートのみで該当 |
| リクエスト形式 | multipart/form-data POST リクエスト 1 回(Next.js は Next-Action ヘッダーを含み、値は任意) |