Reactのサーバーを殺す致命的な欠陥の説明

Reactサーバーコンポーネントにおける重要なCVSS 10.0の脆弱性により、攻撃者は1回のリクエストでサーバー上で任意のコードを実行できる可能性があります。このエクスプロイトの仕組みと、なぜすぐにアプリケーションをパッチする必要があるのかを説明します。

Hero image for: Reactのサーバーを殺す致命的な欠陥の説明
💡

TL;DR / Key Takeaways

Reactサーバーコンポーネントにおける重要なCVSS 10.0の脆弱性により、攻撃者は1回のリクエストでサーバー上で任意のコードを実行できる可能性があります。このエクスプロイトの仕組みと、なぜすぐにアプリケーションをパッチする必要があるのかを説明します。

ウェブを揺るがした警告

最悪の事態が発生しました。React Server Components に、最大の深刻度である CVSS 10.0 のリモートコード実行バグが見つかり、セキュリティ研究者たちはこれを「壊滅的」と迅速に名付けました。リスクは、高トラフィックのプロダクションサイトから趣味の Next.js プロジェクトまで、脆弱な React サーバーパッケージを使用する全アプリに及び、認証されていない攻撃者に対して突然の脅威となりました。特別に作成された HTTP リクエストが、ログインなしでサーバー上で任意のコードを実行する可能性を秘めています。

Reactのメンテナーは、フレームワークのリリースに対して異例の直接的な言葉で反応し、すべての影響を受けたバージョンで「今すぐアップグレードするように」と開発者に促しました。ホスティングプラットフォームも追随し、Vercel、Cloudflareなどは緊急のWAFルールを急いで導入し、これらのフィルターが部分的な防御に過ぎないことを警告しました。セキュリティチームはこのアドバイザリーをゼロデイの火災訓練のように扱い、数時間以内にパッチを本番環境に投入しました。

セキュリティのメーリングリストと赤いバナーで溢れたDiscordチャンネルには、「すぐにパッチを当ててReactを修正せよ」というメッセージが溢れていました。DevOpsチームは機能の展開を凍結し、依存関係のアップグレード、依存関係の固定、再展開を優先しました。通常数日かかるCIパイプラインが、瞬時に新しいReactビルドを出荷するようになりました。

バグの名称は瞬く間に決まりました。研究者たちとReactコミュニティは、同様の悪夢を示す意図的な響きを持つReact2Shellに集まりました。それは、普遍的なコンポーネント、シリアライゼーションの欠陥、そして簡単なリモートコード実行を特徴とするものでした。専用サイトreact2shell.comと、増え続けるGitHubの概念実証エクスプロイトのエコシステムが、このブランドを確立しました。

Log4Shellとの比較は単なるマーケティングではありませんでした。2021年のLog4jのように、React Server Componentsは現代のウェブスタックの奥深くにあり、フレームワークやボイラープレート、テンプレートの背後に隠れています。多くのチームは基本的な質問に答えるだけでも数時間を要しました。「私たちはどこかでReact Server Componentsを実行していて、どのバージョンを使っていますか?」

活発な悪用の報告がほぼ即座に寄せられました。AWSのセキュリティチームは、「サイバー脅威グループがこれを迅速に悪用しようとしている」と警告し、スキャナーがインターネット上で脆弱なNext.jsサーバーを探し回っていました。バグバウンティハンターや犯罪者も、単一のPOSTリクエストを誰かのインフラ上でシェルプロンプトに変えるペイロードを交換し始めました。

React2Shell:CVSS 10.0 の悪夢

イラスト:React2Shell: CVSS 10.0の悪夢
イラスト:React2Shell: CVSS 10.0の悪夢

React2Shellは、バグの最悪の層に位置しています。認証されていないリモートコード実行がインターネットに面したサーバーで発生します。ログインも、CSRFトークンも不要で、ユーザーに何かをクリックさせる必要もありません。巧妙に作成された一つのHTTPリクエストがReactサーバーコンポーネントのエンドポイントに到達すると、攻撃者はあなたのNodeプロセスが持つ特権で任意のコマンドを実行します。

セキュリティ担当者はRCEを恐れています。なぜなら、それは他の防御策をすべて崩壊させるからです。攻撃者がコードを実行できるようになると、環境変数を読み取ったり、データベースをダンプしたり、ウェブシェルを設置したり、クリプトマイナーをインストールしたり、さらにはクラウド内でさらに深く侵入したりすることができます。その時点で、あなたは「データを漏洩させている」のではなく、他の誰かのオペレーションセンターをホスティングしている状態です。

React2ShellはNext.jsにとどまりません。このバグはReactサーバーパッケージとそのReact Flightプロトコルの実装に存在するため、そのスタックに接続する任意のフレームワークが影響を受けます。これには、Waku、React Routerのサーバーサイド機能、およびFlightプロトコルを直接扱うことに決めたカスタムバックエンドなどのプロジェクトが含まれます。

CVSS 10.0はマーケティングの誇張ではなく、標準化されたリスクスケールの最高点です。そのスコアは同時に三つのことを示しています: trivialな悪用可能性、認証の障壁なし、そして機密性、完全性、可用性の完全な侵害です。連鎖バグ、競合状態、またはローカルアクセスは必要ありません。インターネットへの到達可能性と脆弱なバージョンがあれば十分です。

CVSSにおいて、React2Shellはすべての指標で最大値を記録しています:攻撃ベクター:ネットワーク攻撃の複雑さ:低必要な特権:なしユーザーの相互作用:なし。影響の指標も最大値に達しており、任意のコード実行はアプリケーションデータに対する完全な読み書き制御を意味し、サービスをクラッシュさせたり再利用したりする能力を持っています。そのため、勧告はこれを「重要」とタグ付けし、「高」とはしていません。

最もぞっとする詳細:所有されるためにエキゾチックな機能をオンにする必要はありません。脆弱なコードは、React Server Componentsがデフォルトで使用するコアのシリアライゼーションパスに存在しているため、影響を受けたバージョンを使用した新しい「npx create-next-app」は、初日から悪用可能なロジックを含んでいます。サーバーアクションもカスタムデシリアライザーも実験的なフラグも必要ありません。

React2Shellは、ボイラープレートを攻撃面に変えます。あなたのスタックが脆弱なReactサーバーパッケージを通じてFlightと通信し、HTTP経由でアクセス可能な場合、あなたは対象となります。

あなたのアプリは脆弱です(サーバーアクションを使用していなくても)。

React2ShellはServer Actionsの中には存在しません。React Flightプロトコル自体にあり、すべてのReact Server Componentsを動かす低レベルのシリアライザー/デシリアライザーです。もしあなたのスタックが脆弱な`react-server`バージョンでFlightペイロードを解析すると、コードベースに`use server`を記述していなくても、認証されていないリモートコード実行(RCE)が引き継がれます。

Metaの助言では、特定の19.xビルドにおいて`react-server`パッケージが脆弱であると指摘されています。これらのバージョンをバンドルし、Flightエンドポイントを公開するフレームワークは対象となります。そのリストにはNext.jsのほか、React RouterのデータAPIや新たに登場するRSCフレームワークなどが含まれます。

Next.jsのアプリルーターは、特に危険です。なぜなら、デフォルトのアーキテクチャがFlightを自動的に接続するからです。アプリルーターを使用して新しく作成した`create-next-app`と、脆弱なNext.jsリリース(例えば、React 19.0.0–19.2.0と組み合わせた14.x)では、追加の設定なしにFlightのフォームデータを受け入れるエンドポイントが起動します。ビルドしてデプロイすれば、インターネットに晒されたRCEの脆弱性が発生します。

すべてのHTTPハンドラーがサーバーコンポーネントペイロードを消費することで、潜在的なエントリーポイントとなります。それには以下が含まれます: - 組み込みのアプリルーターデータエンドポイント - `renderToReadableStream`や類似のFlight APIを呼び出すカスタムルートハンドラー - FlightペイロードをNodeサーバーに転送するプロキシまたはエッジ関数

認証はデフォルトではあなたを守りません。攻撃者が認証前にFlightエンドポイントにアクセスできる場合、未認証のリモートコード実行(RCE)を得ることになります。もしあなたのFlightパースがログインの背後にあるとしても、それをブラウザに公開している場合、クロスサイトリクエストフォージェリやトークンの盗難は、瞬時に完全なサーバーの侵害へと進展します。

Meta自身の文書「React Server Componentsにおける重大なセキュリティ脆弱性 (CVE-2025-55182)」では、ホスティングプロバイダのWAFルールはあくまで一時的な対策であると明言しています。`react-server`およびあなたのフレームワークにパッチを適用するか、公開されたFlightエンドポイントが既に調査されていると仮定してください。

攻撃の解剖学:サーバーをハッキングするための1つのリクエスト

攻撃者が必要とするのは1つのHTTPリクエストだけです。React2Shellは、React Server Componentsアプリの退屈なPOSTエンドポイントを、React Flightプロトコルがストリーミングされたコンポーネントデータをデシリアライズする方法を悪用してリモートシェルに変えます。認証もCSRFトークンもユーザーセッションも不要です。

攻撃者は、通常のブラウザ送信のように見える悪意のあるPOSTリクエストを作成することから始めます。ボディは`multipart/form-data`を使用しており、これはReact Flightがサーバーコンポーネントのペイロードやサーバーアクションをストリーミングするために使用するのと同じフォーマットです。そのフォームデータの中に、攻撃者はFlightの内部の`$`で始まる参照構文を模倣した一連の「チャンク」を隠しています。

各チャンクは legitimate コンポーネントツリーの一部であるかのように見せかけていますが、その構造は武器化されています。あるフィールドは `$0`、`$1`、`$2` といった他のチャンクを指し、特別に作成されたパス文字列は `:` 区切りを用いてネストされたプロパティにアクセスします。そのパスの中には真のペイロードが埋め込まれており、それは `__proto__` にアクセスし、JavaScript のオブジェクト内部に踏み込もうとする試みです。

脆弱なサーバーがリクエストを受け取ると、ReactのFlightデシリアライザーが自動的に作動します。フォームデータを解析し、チャンクグラフを再構築し、$参照やコロン区切りのパスの解決を開始します。重要なのは、以前のReactサーバーのバージョンは、リクエストされたキーが「自身の」プロパティであるかどうかを確認しなかったため、`__proto__`がそのまま通過してしまったことです。

その oversight は、単純な検索を完全なプロトタイプ汚染に変えてしまいます。`$1:__proto__:execSync` のようなパスを解決することによって、デシリアライザーは攻撃者に汚染されたプロトタイプに付随した `child_process.execSync`(または類似のプリミティブ)への実行参照を渡すことができます。そこから、ペイロードはデシリアライゼーションプロセスの一環としてサーバーに任意のシェルコマンドを実行するよう指示します。

React2Shell上の概念実証コードおよびオリジナルかつ詳細なPOCは、これをワンショットのエクスプロイトに武器化します。攻撃者が作成したPOSTリクエストは、サーバーに「you have been pawned」とエコーするコマンドを実行させ、その後`cat secret.txt`を実行し、サーバーのデスクトップに置かれたファイルを読み取ります。デモでは、内容が直接Next.jsのサーバーログにストリーミングされますが、同じプリミティブを使用することで`curl`を介して秘密を抽出したり、リバースシェルをドロップしたり、単一のリクエストで永続的なマルウェアをインストールしたりすることができます。

欠陥の内部: リアクトフライトプロトコル

イラスト:欠陥の内部:リアクトフライトプロトコル
イラスト:欠陥の内部:リアクトフライトプロトコル

React Flightは、実際の問題を解決するために存在します。それは、React Server Componentsのツリーをバックエンドからブラウザにストリーミングする方法です。サーバーのランタイムの半分をJavaScriptとして送信するのではなく、Reactのチームは、コンポーネント、プロップ、参照を小さな「チャンク」の連続として記述できるカスタムワイヤフォーマットを設計しました。これにより、ネットワークを通じて徐々に流れ込み、クライアント側で段階的にハイドレートされます。

各チャンクは React Flightプロトコル の中でUIの小さな部分を運びます:コンポーネントタイプやプロップ、あるいはプロミスプレースホルダーかもしれません。データの重複を避けるために、Flightは特別な文字列トークンを使用し、"$" で始まる他のチャンクを指します。ペイロードは `"$1"` と言って「チャンク1を見に行け」と示すことができ、また `"$1:name"` と言って「チャンク1に行き、そこに存在するオブジェクト上の `name` パスを辿れ」と示すことができます。

その `$` リファレンスは、デシリアライザーが再構築するオブジェクトのコンパクトなグラフを形成します。チャンク0は単に `["$1"]` であり、チャンク1はチャンク2を指すオブジェクトであることができます。その結果、サーバー側またはクライアント側では、ワイヤ形式がインデックスとパス文字列の奇妙な混合に見えるにもかかわらず、清潔なJavaScriptオブジェクト `{ name: "cherry" }` になります。

React2Shellの根本的な原因は、そのパス追従ロジックに潜んでいます。Flightのデシリアライザーは、`"$1:__proto__:toString"`のような攻撃者が制御するパストラバーサル命令を喜んで受け入れ、それらを確認せずに進んでしまいました。ガードレールもなく、プロパティチェックもなく、ただパス文字列が示すものに対する生のアクセスが許可されていました。

ユーザーデータで止まるのではなく、そのトラバースステップはJavaScriptの内部にまで到達しました。プレーンオブジェクト上の`__proto__`といったパスを解決することで、デシリアライザはクラシックなプロトタイプ汚染への扉を開きました。そこから攻撃者は強力なビルトイン機能にチェーンし、最終的には`child_process`に実行を誘導し、単一の悪意のあるリクエストでリモートコード実行を達成しました。

ここではJSONはつまらなく、また安全だったでしょう。標準のJSONは参照、パス、または特別な`$`セマンティクスが欠けており、データを記述するだけで、どのように歩いたり再構築したりするかを説明していません。Flightの特注フォーマットは、クロスチャンク参照とトラバーサル構文を追加しましたが、成熟したシリアライザーやJSONパーサーが長年のセキュリティレビューを経て蓄積してきた堅固な検証レイヤーは持っていませんでした。

カスタムプロトコルは常に柔軟性との引き換えに安全性を犠牲にします。ReactのFlightフォーマットは、`"$1:foo:bar"`のような文字列の中にアドホックなミニ言語を作ることによって、一般的なツール—JSONバリデーター、スキーマチェッカー、WAFルール—が理解できない新たな攻撃面を生み出しました。そのミニ言語が`__proto__`に触れることができるようになると、React Server Componentsを使用しているすべてのサーバーは同じ重大な欠陥を引き継ぐことになりました。

パス遍歴からプロトタイプ汚染へ

プロトタイプ汚染は抽象的に聞こえるかもしれませんが、JavaScriptにおいては出荷することのできる最も危険なバグの一つです。単一のオブジェクトを破損させるのではなく、プロトタイプ汚染は攻撃者が`Object.prototype`自体、つまりNodeやブラウザプロセス内のほぼすべてのオブジェクトの共有祖先を改ざんできるようにします。そのルートが侵害されると、オブジェクトグラフ全体が攻撃者が制御するプロパティを継承し始めます。

React Server Componentsは、そのReact Flight Protocolのパストラバーサルロジックによってこの罠に陥りました。デシリアライザーはネストされた構造を歩くためのコロンベースの構文をサポートしているため、`:$1:fruit:name`という参照は「チャンク1をたどり、次に`fruit`、その後`name`をたどる」という意味です。研究者たちは、通常のキーをJavaScriptの内部に置き換えて` :__proto__`を要求することを止めるものは何もないことに気付きました。

その一つの変更が、利便性の機能を武器に変えました。脆弱なコードは`__proto__`のようなパスセグメントを見つけると、それを単なるプロパティとして扱い、無防備に`value['__proto__']`に進んでしまいました。JavaScriptでは、そのジャンプによってターゲットの生の`Object.prototype`を手に入れることになり、データバグ上の無害なフィールドではありません。

一度攻撃経路が `__proto__` に到達すると、攻撃者はそれに書き込みを始めることができました。加工されたFlightチャンクを送信することで、例えば `payload: { ":$1:__proto__:pwned": "yes" }` のようなことができ、これにより `Object.prototype.pwned = "yes"` が設定されます。その瞬間から、プロセス内のすべてのプレーンオブジェクトには突然 `pwned` プロパティが追加され、攻撃リクエストが完了した後に作成されたオブジェクトさえも含まれます。

汚染は文字列のフラグで止まりません。攻撃者は、`Object.prototype.toJSON` や、下流のコードが信頼するカスタムフックなど、プロトタイプに完全な関数を注入することができます。もし後のライブラリが `JSON.stringify(user)` を実行したり、`options.onSuccess?.()` を呼び出した場合、数分前にプロトタイプに接合された攻撃者が提供したコードが実行される可能性があります。

React2Shellは、スタック内の強力であまり監査されない場所を標的にして、リモートコード実行にこれを繋げます。たとえば、汚染されたプロパティは、フレームワークがシェルコマンド、ファイルパス、または動的な`require`呼び出しを構築する方法に影響を与える可能性があります。一旦汚染された値が`child_process.exec`、テンプレートエンジン、または動的インポートに流れ込むと、「奇妙な余分なフィールド」から「サーバー上の任意のコマンド」へのジャンプは一行で発生します。

NVDエントリCVE-2025-55182の完全な技術詳細と詳細な実証サンプルでは、単一のHTTPリクエストがどのようにして`Object.prototype`を汚染し、その後に腐敗したプロパティをNodeの最も危険なAPIに持ち込むかが示されています。その組み合わせがCVSS 10.0のスコアを正当化しています:一つの認証されていないリクエストで、全プロセスが侵害されるのです。

最終チェーン:コードを実行するために約束を乗っ取る

プロトタイプの汚染だけではシェルを得ることはできません。攻撃者は依然として、破損したオブジェクトグラフを実行中のシステムコマンドに変換する方法が必要です。React2Shellの最終的なトリックは、その汚染されたプロトタイプを完全に武器化されたリモートコード実行パスにチェインするもので、使用されるのはJavaScriptの自らのリフレクション機能と非同期セマンティクスのみです。

攻撃者が基本オブジェクトプロトタイプを制御することができると、プロトタイプチェーンをたどってグローバルな Function コンストラクタに到達することができます。JavaScriptでは、すべての関数は最終的には `Function.prototype` から継承されており、`Function` 自体は `({}).constructor.constructor` のようなコンストラクタを介してアクセス可能です。

そのアクセスを利用することで、ペイロードはすべての「no eval」バイパスが行うことを単に行います:`new Function("require('child_process').execSync('id > /tmp/pwned');")`。その文字列は任意のシェルコマンドを保持できます:データを流出させるための`curl`、ディスクを消去するための`rm -rf`、またはリバースシェルを仕込むためのワンライナー。Next.jsサーバー上では、これらのコマンドはNodeプロセスと同じ権限で実行されるため、環境変数、APIキー、プライベートファイルに直接アクセスできることがよくあります。

攻撃者は依然として一つの問題に直面していた:悪意のある関数を作成することはできるが、明らかなコールサイトを制御することができなかった。彼らは、自身の関数を自動的に呼び出すために、アプリケーションコード内で明示的な `malicious()` コールなしにサーバーの制御フローを必要としていた。

JavaScriptの`await`キーワードが欠けていたリンクを提供しました。内部では、`await value`は`value`が「thenable」であるかどうかを確認し、もしそうであれば`value.then(resolve, reject)`を呼び出します。その静かな動作こそがPromiseを支えており、まさにReact2Shellがそれを悪用しています。

共有のプロトタイプを汚染して、攻撃者のFunctionインスタンスを指す`.then`プロパティを定義することによって、待機されているオブジェクトは突然トリガーとなりました。Reactサーバーコンポーネントのコードがデシリアライズされた値で`await`に達すると、JSエンジンは怠らずに`.then`を呼び出し、今や任意のシェルコマンドが実行されました。追加のフックや奇妙なガジェットは不要で、通常の非同期コードパスが普遍的なRCEトランポリンに変貌しました。

Reactを救った簡単な解決策

イラスト:Reactを救ったシンプルな解決策
イラスト:Reactを救ったシンプルな解決策

ReactのReact2Shellに対する修正は、ほとんど侮辱的に簡単に見えます。パストラバーサルからプロトタイプ汚染、ハイジャックされたPromise、`child_process.execSync`へと続く一連の問題に対して、Reactチームの公式パッチは本質的に一つのゲートキーパーを追加しています。それは、Flightのデシリアライズ中にプロパティを読み込む前に`Object.prototype.hasOwnProperty`を呼び出す単一の`if`文です。

無条件に `value = value[path]` を各セグメントに対して行うのではなく、パッチを当てたコードはまず `if (!Object.prototype.hasOwnProperty.call(value, path))` をチェックし、キーが欠けている場合はエラーで終了します。この小さな条件により、「JavaScriptオブジェクトモデル全体を歩き回る」といった動作から「このオブジェクトが実際に所有しているフィールドのみを信頼する」動作に切り替わります。プロトタイプチェーンにのみ存在する悪意のある `__proto__` 参照は、突然厳しい壁に直面します。

これは、`hasOwnProperty`が継承されたプロトタイプチェーンを完全に無視するために機能します。JavaScriptでは、すべての通常のオブジェクトが`Object.prototype`から継承しています。このプロトタイプには、危険なメタプロパティである`__proto__`や`constructor`が存在します。ReactのFlightプロトコルが、すべてのデリファレンスされたキーを「自身のプロパティ」であることを強く要求することで、攻撃者がそれらの内部に触れることを防ぎ、汚染されたプロトタイプが決して現れないようにします。

セキュリティ研究者たちは、多くの壊滅的なバグが欠落したチェックに起因することが多いとよく言います。そして、React2Shellはそのことを証明しています。パッチが適用される前、デシリアライザーはクライアントが送信したパスを暗黙的に信頼しており、それがJavaScriptの内部に直結していても関係ありませんでした。その後、一つの`if`文がCVSS 10.0のRCEチェーンを退屈な「無効な参照」エラーに変えてしまいます。

数千のReact Server Componentsのデプロイにおける未認証のRCEを背景に見ると、その洗練された構造はほとんど不気味です。React Server ComponentsとNext.jsに基づく広大なエコシステムは、本来初日から存在すべきだった単一のガードレールに依存しています。今や、ルーチンのサーバーレンダリングと完全なサーバー乗っ取りの間には、1行の防御コードが隔てています。

フォールアウト:アクティブなエクスプロイトとWAFバイパス

React2Shellは、理論的な悪夢から実用的な攻撃キットへと数日で移行しました。証明概念のリポジトリ、エクスプロイトの説明、そして実行可能なペイロードがすでにGitHubに公開されており、国家規模の攻撃から週末の愛好者まで、参入障壁が大幅に低下しています。脆弱なReactサーバーコンポーネントを実行しているインターネット向けのアプリは、効果的に「ポート443で利用可能な認証なしシェルを提供中」と宣伝しています。

セキュリティチームはすでに影響を感じています。AWSは「サイバー脅威グループがこれを迅速に利用しようとしている」と報告しており、スキャナーが広範なIPレンジで反応の兆候となるReact Flightエンドポイントを探し回っています。独立した研究者やMSSPは、誤ったフライトペイロードを送信し、微妙なタイミングやエラーの違いを監視して脆弱なターゲットを特定する急増するプローブを説明しています。

攻撃者は、元の脆弱性のピクセル単位の完璧なコピーを必要としません。公開されたPoCや、CVE-2025-55182 (React2Shell): Reactサーバーコンポーネントにおけるリモートコード実行のような詳細な解説があれば、ペイロードを無限に変異させることができます。フィールド名を変更したり、チャンクの順序を入れ替えたり、汚染されたプロトタイプチェーンを追加の間接レベルの背後に隠したりすることで、ほとんどのWAFルールが期待するシグネチャから既に逸脱しています。

ホスティングプロバイダーは緊急フィルターを急いで展開しました。Vercel、Cloudflare、AWSは、マルチパートフォームデータ内の `__proto__` リファレンスや疑わしい `$` プレフィックス付きチャンクリファレンスといった明白なReact Flightの悪用パターンをブロックするWAFのアップデートを行いました。これらのルールはコピーペースト攻撃に対抗するのに役立ちますが、根本的にはサーバーが入力を逆シリアル化する方法に存在するバグの既知の形状にのみ対応しています。

歴史は、WAF専用の防御が劣化することを示しています。CVSS 10.0のRCEが公開されると、エクスプロイトの著者はベンダーが新しいシグネチャを出荷するよりも速く繰り返し改良します。オブフスケーションのトリック—ユニコードのホモグリフ、`constructor.prototype`のような代替アクセスパス、ネストされた配列、または圧縮されたペイロード—は、一般的な「この文字列をブロックする」フィルターを普通に回避します。

唯一のコントロールは、エンゲージメントのルールを変更します:パッチ適用です。React、Next.js、及び脆弱なReactサーバーパッケージを埋め込んだ任意のフレームワークをアップグレードすることで、安全でないFlightのデシリアライズを完全に排除できます。巧妙なWAF設定のどれも、そもそもバグを実行しない確実性には敵いません。

これはReactの「Log4Shell」瞬間なのでしょうか?

React2Shellは、1つのシンプルな理由からLog4Shellとの比較をすぐに促しています。それは「影響範囲」です。単一の認証されていないPOSTリクエストが、脆弱なReact Server Componentsを使用しているほぼすべてのアプリでリモートコード実行を引き起こす可能性があります。趣味で作成されたNext.jsプロジェクトから高トラフィックのSaaSダッシュボードまでです。Log4Shellと同様に、このバグは、数千のチームが明示的にオンにした「セキュリティに敏感な」機能ではなく、暗黙のうちに採用したインフラコードに存在します。

Log4ShellはJavaスタックにおけるLog4jの普及に乗じて発生しましたが、React2Shellは現代のウェブフロントエンドにおけるReactの優位性に乗っかっています。React Flightプロトコルを組み込んだフレームワーク—Next.js、React RouterのデータAPI、新興のRSCフレームワーク—は突然、CVSS 10.0という負債を引き受けることになりました。このようなエコシステムレベルの依存リスクこそが、Log4Shellを10年に一度の事件にした要因です。

Log4Shellがロギングライブラリについての前提を打ち壊したところで、React2Shellは「フロントエンド」フレームワークのメンタルモデルを粉砕します。Reactサーバーコンポーネントはクライアントとサーバーの境界をぼかしますが、このバグはセキュリティの境界も曖昧になったことを証明します。コンポーネントツリーは今やプロトコルの表面としても機能し、シリアライズ形式は静かにリモートコード実行の原始的手段となりました。

セキュリティの責任は以前は明確に分かれていました。バックエンドチームはAPIやデータベースを守り、フロントエンドチームはXSSやCSRFを気にしていました。しかし、RSC時代のスタックはその境界を消し去ります。JSXコンポーネントがカスタムワイヤーフォーマットを介してサーバーロジックをトリガーできるようになると、「フロントエンド」の変更がバックエンドの脆弱性を引き起こす可能性があり、どちらの側も完全に責任を感じないかもしれません。

開発者は今、不快な質問をしなければならない:サーバーコンポーネントには、実際に理解できるセキュリティモデルが存在するのか?React2Shellは、この1週間の前にFlightの内部構造を理解している人がどれほど少なかったかを露呈しました。その中には、それを本番環境にデプロイした多くの人も含まれています。もしどの入力がデシリアライザに届くのか説明できないなら、アプリの脅威モデルを意味のある形で考えることはできません。

フレームワークの著者は、より厳しい義務に直面しています。FlightやRemixのデータローダー、tRPCのカスタムエンコーディングなどのプロトコルは、ORMクエリビルダーやTLSスタックと同じ程度の精査を受けるべきです。つまり、形式的な脅威モデル、ファジング、レッドチームレビュー、シリアライズや参照解決、クロスバウンダリーデータフローに焦点を当てた第三者監査が必要です。

Reactの迅速なパッチによって、Log4Shell規模の完全な崩壊は防がれましたが、その警告は大きな意味を持ちます。ネットワークを通じてロジックが移動するツールは、どんなに「フロントエンド」に見えても、明確に重要な攻撃面のカテゴリーに属することになります。

よくあるご質問

React2Shellの脆弱性(CVE-2025-55182)とは何ですか?

React2Shellは、React Server Componentsにおける重要な認証不要のリモートコード実行(RCE)脆弱性です。この脆弱性により、攻撃者は単一の悪意のあるリクエストを使用してサーバー上で任意のコードを実行することができ、CVSS 10.0の最高の深刻度スコアを持っています。

どのバージョンのReactとNext.jsが影響を受けていますか?

この脆弱性は、React Serverのバージョン19.0.0から19.2.0に影響を与えます。これには、それを使用しているフレームワーク、例えばNext.jsが含まれます。デモで示されている16.0.6バージョンのように、影響を受けているReact Serverバージョンを使用しているNext.jsの任意のバージョンが脆弱です。ユーザーはすぐに最新のパッチが適用されたバージョンにアップグレードする必要があります。

React2Shellの脆弱性はどのように機能しますか?

この脆弱性は、React Flightプロトコルにおける安全でないデシリアライズの欠陥を悪用します。攻撃者が特別に作成されたペイロードを送信することで、「プロトタイプ汚染」脆弱性を引き起こし、コアJavaScriptオブジェクトの動作を変更して最終的にコマンドを連結し、サーバー上でコードを実行することができます。

WAFは、React2Shellからアプリケーションを保護するには十分ですか?

いいえ。VercelやCloudflareなどのプロバイダーから提供されるWebアプリケーションファイアウォール(WAF)は既知の攻撃パターンをブロックできますが、完全な解決策ではありません。攻撃者はしばしばペイロードを難読化してWAFルールを回避することができます。信頼できる唯一の対策は、ReactとNext.jsの依存関係をパッチが適用されたバージョンにアップグレードすることです。

🚀Discover More

Stay Ahead of the AI Curve

Discover the best AI tools, agents, and MCP servers curated by Stork.AI. Find the right solutions to supercharge your workflow.

Back to all posts