概要
2025年12月、Web 開発のエコシステムを揺るがす深刻なセキュリティ脆弱性、React2Shellが公開された。この脆弱性は、React Server Components と Flight プロトコルを使用するアプリケーションで発生し、攻撃者はたった1回の HTTP リクエストでサーバー上で任意のコードを実行することができる。CVSS スコアは10.0(Critical)で評価され、認証なしに攻撃が可能であるという点から、その波及効果は非常に大きい。本記事では、React2Shell(CVE-2025-55182)の発生原理と攻撃フロー(React Server Components の Flight 処理過程における、逆シリアライズの悪用)を整理し、脆弱性の対応策を紹介する。
技術背景
React Server Components & Server Action
React 18 の時点で React Server Components(RSC)が実験的に導入され、UI を Server Component と Client Component に分離し、サーバーでレンダリングした結果をクライアントに伝達するモデルが提案された。これにより、インタラクションが必要な一部のみを Client Component に維持し、残りを Server Component に置くことで、クライアントサイドの JavaScript バンドルサイズを削減し、クライアントの処理負担を軽減することができる。クライアントからサーバー側にリクエストを行う際、リクエストデータをシリアライズするプロセスが進行するが、このプロセスで React Flight プロトコルが活用される。
React Flight プロトコル
React Flight プロトコルは、React コンポーネントツリー、データ、サーバーリファレンス(Server Reference)などをサーバーとクライアント間で効率的に送信するために設計されたカスタムシリアライズフォーマットである。
Flight プロトコルはデータを chunk という独立した単位に分けて管理し、各 chunk は固有 ID を持つ。データシリアライズ時、特殊な値や他の chunk に対する参照は $ 接頭辞が付いた文字列で表現される。この参照システムは、逆シリアライズプロセスにおいて元のオブジェクトや値に復元される。
主な参照タイプは以下の通りである。
|
接頭辞 |
タイプ |
説明 |
|---|---|---|
| $@ | Promise/Chunk | 特定 ID Chunk に対する参照 |
| $B | Blob | 特定 ID Chunk の Blob データ参照 |
| $Q | Map | 特定 ID Chunk の Map オブジェクト参照 |
| $0-9a-f | Chunk 参照 | 16進数 ID を持つ Chunk に対する参照 |
[表 1] Flight プロトコル接頭辞
CVE-2025-55182
今回発見された React Server Components の致命的な脆弱性(CVE-2025-55182, React2Shell)は、Flight プロトコルのペイロードをサーバー側で逆シリアライズ(Deserialization)すると、安全でない検証により発生する。すなわち、クライアントからサーバーに送信された Flight プロトコルのペイロードに対する検証が不完全であることから発生した問題である。この攻撃に対する核心の脆弱性は大きく三つに分けることができ、全体の攻撃は三つの脆弱性の連携で完成する。
1) Fake Chunk 注入
React は内部で逆シリアライズされたデータを chunk オブジェクトで管理する。Chunk オブジェクトは以下のように「status」、「value」、「reason」、「_response」プロパティを持つ。

[図 1] Chunk プロパティ
サーバーの Chunk.prototype.then 処理フローで、攻撃者が Chunk のように見えるオブジェクトを注入し、status が resolved_model で処理される経路に誘導すると、initializeModelChunk が呼び出されるフローにつながる。

[図 2] Chunk.prototype.then
攻撃者がこれを悪用し、以下のペイロードの一部のようにペイロード内部に fake chunk JSON オブジェクトを入れても、initializeModelChunk を呼び出す。このとき、攻撃者の悪意のあるペイロードを保持している「_response”:」部分がそのまま chunk の _response プロパティに割り当てられる。
2) 検証のないプロパティパスの巡回によるプロトタイプチェーンアクセス/汚染
Flight プロトコルはコロン(:)で区切られたパスを使用し、ネストされたオブジェクトのプロパティにアクセスできる。
問題は getOutlinedModel 関数でこのパスを処理したあと、呼び出す createModelResolver 関数内で発生する。

[図 3] 脆弱な createModelResolver
このコードは、参照パスの各部分をオブジェクトのプロパティキーで使用し、順次値にアクセスする。このとき、value[path[i]]に該当するプロパティ名に対する検証を一切行わない。hasOwnProperty を利用した確認がないため、攻撃者は __proto__ や constructor のような JavaScript の「マジックプロパティ」をパスに含めることで、プロトタイプチェーンを遡ることができる。
このように、ユーザーが制御する入力値を通じてオブジェクトのプロトタイプを汚染する攻撃手法をプロトタイプ汚染(Prototype Pollution)と言い、これが全体の攻撃の基盤となる。
3) Function コンストラクタ Gadget 構成によるコード実行
Prototype Pollution で窃取された Function コンストラクタは、注入された偽の _response オブジェクト内の _formData.get メソッドを上書きする際に使用される。結果的に、_response._formData.get は、もはや一般的な get 関数ではなく、文字列をコードとして実行できる Function コンストラクタ自体になる。
“then”:“$B1337” パース過程で、response._formData.get 関数が呼び出され、引数に渡される response._prefix は、攻撃者が制御するコード文字列(またはコードの組み合わせ要素)として悪用されることができる。このように作成された関数オブジェクトは、promise resolution の過程で .then() の呼び出しと同時に実行される。

[図 4] parseModelSring: “$B” パース
攻撃シナリオ

[図 5] 攻撃シナリオフローチャート
この脆弱性が発生する環境を前提に攻撃が行われた場合、シナリオは以下の通りである。攻撃者は外部からアクセスできる RSC リクエスト処理経路に、操作された HTTP POST リクエストを送信する。サーバーは、このリクエストを正常な RSC 処理フローとして受け取り、Flight 形式のデータを読み込んで、攻撃者が意図した形で「チャンク(Chunk)のように見えるデータ」が内部の処理過程に混ざるように仕向ける。すなわち、サーバーが本来行おうとしていた「リクエストデータ復元」過程に、攻撃者が準備した構造物が自然に混ざり込む状況を誘導する。
その後、サーバーは参照パスに沿ってオブジェクトのプロパティを探す過程を経るが、このパスが十分に検証されていない場合、__proto__ や constructor のようなキーを利用してプロトタイプチェーンの方に抜け出すことができる。攻撃者は、この地点を利用しサーバー側のオブジェクト状態を有利に変えたあと、最後には constructor.constructor のような方式で Function コンストラクタまで到達する Gadget を成り立たせ、自分が送った文字列が関数にして実行されるように誘導する。結果的に、前述で整理した三つの欠陥が順番通りに繋がると、たった一度のリクエスト処理フローの中でサーバーで任意のコード実行まで繋がることができる。
対応策
最も重要で根本的な解決策は、脆弱性が修正されたバージョンに関連パッケージを即時アップデート後、再配布することである。すぐにパッケージのアップグレードと再配布ができない場合、リクエストの本文に __proto__ または constructor のようなキーワードが含まれた Flight プロトコルのペイロードを検知し、遮断するルールを適用する方法もある。これは、完璧な解決策ではないが、既知の攻撃パターンを防ぐのに役立つことができる。
アップデートおよび再配布、遮断ルールの適用の他にも、危険を最小化するために、ビジネスに必須でないサーバーアクション機能は一時的に無効にする方法も検討できる。または、すべてのサーバーアクションエンドポイントに対して強力なユーザー認証および権限検証ロジックを追加し、匿名の攻撃者がアクセスできないように防がなければならない。
AhnLab 対応状況
AhnLab 製品群の検知名とエンジンバージョン情報は以下の通りである。
EDR 検知
- InitialAccess/EDR.Event.M13379(2025.12.17.02)
- InitialAccess/EDR.Event.M13380(2025.12.17.02)
結論
CVE-2025-55182 脆弱性は、最新の Web フレームワークの複雑性がどのように予測不可能な新しい攻撃ベクターを生み出すことができるのかを示している重要な事例である。これは、開発者のビジネスロジックではなくフレームワーク/依存性(ライブラリ)自体のコアロジックに存在する高リスクの脆弱性であり、その波及効果はエコシステム全体に及ぶ。React サーバーコンポーネントや Flight プロトコルのような革新的な技術は開発の便利さを大幅に向上させたが、その内部動作の複雑性の裏に隠れているセキュリティ脅威は非常に致命的である。
対応するためには、影響を受ける RSC 関連のパッケージおよびこれを含むフレームワークを直ちに最新のセキュリティバージョンにアップデートし、Server Function/Server Action の処理経路が外部に公開されているサービスは優先度を上げて点検しなければならない。本脆弱性に関する詳細な技術解析は、AhnLab ATIP で提供する「React2Shell 脆弱性解析レポート(CVE-2025-55182) – AhnLab TIP」を通して確認できる。
出典
- https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
- https://github.com/lachlan2k/React2Shell-CVE-2025-55182-original-poc
- https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3
- https://github.com/facebook/react/pull/35277/commits/e2fd5dc6ad973dd3f220056404d0ae0a8707998d?diff=split&w=0
- https://www.cve.org/CVERecord?id=CVE-2025-55182
Categories: 脆弱性