世界を動かす技術を、日本語で。

React2Shellの物語

概要

  • 2025年11月30日、 React2Shell という重大なRCE脆弱性をMetaに報告
  • 12月3日、Metaが CVE-2025-55182 として修正とアドバイザリ公開
  • 脆弱性発見のきっかけは Reactのプロトコル調査 から
  • Next.jsやReact Server Components の仕組みが攻撃面を拡大
  • Flightプロトコル解析 から脆弱性発見と攻撃方法確立までの経緯

React2Shell脆弱性発見の経緯

  • 2025年11月30日、Metaに React2Shell (リモートコード実行脆弱性)を報告
    • 12月3日、Metaが CVE-2025-55182 として修正・アドバイザリ公開
    • 開発者に 即時アップデート を強く推奨
  • 発見のきっかけは Reactのプロトコル調査 を目的とした自主的な学習
  • Next.js などのモダンWebアプリで多用される React Server Components (RSC)Server Functions の内部挙動に着目
  • Flightプロトコル という独自通信仕様の存在を確認
    • 公式ドキュメントがほぼ存在せず、 「no docs, only code」 状態
  • Flightプロトコルの特徴
    • JSONベース だが、 Date, BigInt, Map, Promise 等の複雑な型や参照もサポート
    • メッセージは「チャンク」として分割・非同期送信
    • $記法 で型や参照を表現(例:$DでDate、$xで参照)
  • 解析の過程で プロトタイプ汚染 に類似した動作を発見
    • Flightでオブジェクトの 継承プロパティ (例:Number.prototype.toString)も参照可能
    • 「重大な安全性チェックの欠如」 と指摘される
  • 初期の攻撃仮説
    • Flight経由で 型チェックを回避 し、開発者が想定しない型のオブジェクトをサーバーへ送信可能
    • TypeScriptの型注釈 はビルド時のみ有効で、ランタイムでは無効
  • 具体的な攻撃例
    • toStringやreplaceAllに 悪意ある関数 を注入し、サーバー側で実行させる
    • Functionコンストラクタ へのアクセスにより任意コード実行の可能性
  • 攻撃成立の条件
    • 開発者が 入力値検証を怠る こと
    • Flight経由で 任意の関数・引数 を指定できること

Flightプロトコルの技術的詳細

  • Flight はNext.jsやReactでクライアント・サーバー間の オブジェクト転送 を効率化
    • 非JSON型循環参照非同期データ(Promise) も表現可能
  • メッセージ例
    • 0={ "email": "foo@bar.com", "updated": "$D04 Dec 1995 00:12:00 GMT", "details": "$1" }
    • &1={ "firstName": "$2", "lastName": "$3:foo" }
    • &2="John"
    • &3={ "foo": "Doe" }
  • 受信側で 複雑なJavaScriptオブジェクト に復元
  • $記法 を悪用し、プロトタイプの関数やプロパティへ 意図的にアクセス可能

型安全性の幻想と攻撃手法

  • TypeScript の型注釈は ランタイム検証を伴わない ため、攻撃者は 任意の型 を送信可能
  • 例1:toStringプロパティに関数を仕込むことで、サーバー側の暗黙的な型変換時に 任意コード実行
  • 例2:replaceAll等のメソッド呼び出し時に 攻撃者制御の関数・引数 を注入
  • Functionコンストラクタ 経由で 任意JavaScriptコード の生成・実行が可能
  • Flightメッセージ の構築ルール
    • オブジェクト、配列、文字列、特殊定数、Date/Set/Map/TypedArray、Promise、サーバー関数参照
    • それぞれの プロパティ・メソッド も任意参照可能

脆弱性発見までの試行錯誤

  • Flightの挙動を詳細に解析し、 攻撃可能性のあるパターン を探索
  • Sylvie Mayer との協力でCTF的な問題解決アプローチを採用
  • React/Flightの内部にも ユーザー入力を安全に扱わない例 が存在
  • Reactは堅牢」という先入観から一時的に盲点となる
  • 最終的に decodeReply 等の内部処理で 安全性チェックが欠如 している点を突き止める

React2Shell発見後の対応と影響

  • 脆弱性報告後、Metaが 即座にパッチリリース ・アドバイザリ公開
  • Next.js/React を利用する 数百万サイト が影響
  • Flightプロトコルの仕様・実装の見直しが迫られる
  • 開発者・セキュリティ研究者 にとっての教訓
    • 型安全性に過信しない
    • 独自プロトコルの安全設計実装時の検証 の重要性
    • 公式ドキュメントや仕様公開 の必要性

まとめ

  • React2Shell は、 Flightプロトコル の設計・実装上の盲点を突いた 重大なリモートコード実行脆弱性
  • 型安全性やフレームワークの堅牢性に 過信せず入力値検証 の徹底が不可欠
  • 独自プロトコル 利用時は、 セキュリティ仕様・ドキュメントの明文化 が重要
  • Metaの迅速な対応コミュニティの協力 が被害拡大を防止

Hackerたちの意見

いい読み物だった!「私たちは戻ってきた」と「もう終わりだ」のグラフが大好き。こういう仕事の本質をよく表してるよね。「え?…いや…すごい?!…いや…」

R2Sは辛かったけど、ラクリンは一緒にやるには最高のセキュリティリサーチャーだったよ。責任ある開示の観点だけじゃなくて、メタや私たちのチームと何度も電話をして、修正を確認する手助けをしてくれたからね。ラクリン、インターネットを安全にしてくれてありがとう(この「迷宮」の脆弱性を解明してくれたのも素晴らしい仕事だよ)。

お前はReactを台無しにした。でも、お前にはかなりの利益があったんだろうね。

すごくいいまとめだね。この興味深い脆弱性とエクスプロイトを見つけた経緯を共有してくれてありがとう。

驚くことに、週末にもかかわらず、メタのチームは私の提出物を約17時間でトリアージ、再現、確認してくれた。信じられない。最初から最後まで(確認付きで)24時間以内にやったことを実感してほしい。

これが発覚したときは本当に驚いた。プロトコルがほぼ文書化されていないことに気づいたからね。妥協の指標を探していたんだけど、ドキュメントがないせいで難しくなった。でも、開示前にクラウドフレアみたいなWAFプロバイダーと連携してルールを整えてくれたのは本当に助かったよ。

いい読み物だね。シルビーのまとめもいいよ: https://sylvie.fyi/posts/react2shell/

まだReactサーバーコンポーネントが開発者体験にとって災害以外の何物でもないとは納得できてない。明確な境界なしにバックエンドとフロントエンドを混ぜるのは、数人の貢献者を超えたコードベースにはひどいことだよ。

でも、めっちゃクールだよね!なんでみんながSpringやASP.NETのアノテーションについて文句言って、Next.jsの使い方に飛びつくのか全然理解できない。

それの主な動機は、ある特定のユーザー体験なんだと思う。彼らがそのユーザー体験を提供するための最高の開発者体験を見つけたかどうかはわからないけど、より良いDXが可能かどうかも疑問だね。全体的にかなりの複雑さがあるから。もちろん、結論としては、その種のユーザー体験を作るのは実現不可能だとも言えるかも。幸いなことに、従来のパターンは今でもちゃんと機能するし。

個人的には同意できないし、私の経験ではRSCはウェブサイトを構築する際の内在する複雑さを受け入れていると思う。すべてのウェブサイトは、ある程度サーバーとクライアントを跨いでいるからね。これらの境界を扱うためのツールを提供することは、実際には開発者の自律性とユーザー体験に対する柔軟なコントロールを求めることなんだ。ドメインが複雑だからこそ、複雑なんだよね。ウェブをプラットフォームとして深く理解する必要があるけど、ほとんどのハイレベルなウェブサイトはRSCのアイデアから恩恵を受けることができると思う。多くの人が言うほど足を引っ張るものではないと思うけど、サーバーとクライアントの両方を深く理解していないと、もちろん混乱するよね。FUDに陥らずに、利点と欠点について正直に話したい人には、もっと掘り下げて話すのもいいよ。たとえそれが自分に合わないと思っても、すべてのウェブ開発者が彼らのモデルから何かを得られると思うし。RSCはサーバーを必要としないことも常に注目に値するし、サーバーなしでも価値をもたらすんだよね。

この書き込み、めっちゃ好きだった!特にシルビーの視点が良くて、ホワイトハットハッキングの経済的側面が垣間見えたのが良かったな。準備や安全性、誰を信じるか、できるだけ多くのバグバウンティを獲得するための準備とか。すごく理にかなった経済的フィルターに感心したよ。「バグバウンティプログラムを持っている脆弱な人は誰か?」って。バグバウンティプログラムを持ってないと、誰も連絡してこないかもしれないっていうのは、ほんとにいいリマインダーだね。気づいた時には、もう侵害されてるかもしれないけど。

このサイトが「prefers-reduced-motion」を尊重してくれたらいいのに。背景のドットが、読もうとするときに動揺を引き起こすんだ。Firefoxのリーダーモードに感謝!

最初のエクスプロイトは、bf言語の洗練されたjsonバージョンみたいに見えるね。