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

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

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

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

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

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/freeqaz/react2shell
Динамический анализ (песочница)Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеСтатьи и ИсследованияОбучение и ОбразованиеРазработка Полезной Нагрузки
GitHubfreeqaz/react2shell

react2shell

Набор инструментов для эксплуатации RCE для CVE-2025-55182 и CVE-2025-66478 в React Server Components. Включает несколько вариантов эксплойтов, скрипты обнаружения, уязвимый тестовый сервер и глубокий технический анализ уязвимости десериализации протокола Flight.

681869 месяцев назадПроверено Kitploit
Репозиторий

Популярное

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

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

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

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

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

React2Shell: RCE 0-day в React Server Components

CVE-2025-55182 (React) и CVE-2025-66478 (Next.js)

Этот репозиторий содержит код эксплойта только для авторизованного тестирования безопасности и образовательных целей.

См. также: Несколько исследователей опубликовали анализ этой уязвимости. Ознакомьтесь с разделом Ссылки для получения дополнительных точек зрения, методов эксплуатации и методов обнаружения.

Что это?

В среду, 3 декабря 2025 года, была публично раскрыта критическая уязвимость удаленного выполнения кода в React Server Components. Ошибка, получившая название "React2Shell", позволяет неавторизованному злоумышленнику выполнить произвольный код на любом сервере, работающем под уязвимыми версиями React RSC или Next.js App Router, отправив один HTTP-запрос.

Учитывая, насколько повсеместным стал Next.js - он работает на значительной части современного веба - влияние этой уязвимости серьезно. Любое приложение Next.js, использующее App Router (по умолчанию для новых проектов с Next.js 13) с включенным RSC, уязвимо. Никакой специальной настройки. Никаких конкретных конечных точек. Просто POST-запрос к любому маршруту.

Уязвимость находится в протоколе "Flight" React, формате сериализации, используемом для передачи данных между сервером и клиентом в React Server Components. Отсутствие проверки hasOwnProperty во время десериализации позволяет обход цепочки прототипов, в конечном итоге достигая конструктора JavaScript Function для выполнения кода, контролируемого злоумышленником.

Дефект существует в пакетах React react-server-dom-webpack, и . Next.js, как доминирующий потребитель RSC, наследует уязвимость через свой App Router.

react-server-dom-turbopack
react-server-dom-parcel

Кто подвержен влиянию?

Многие сервисы потенциально уязвимы. Next.js - один из самых популярных фреймворков React, используемый компаниями всех размеров - от стартапов до крупных предприятий. App Router с React Server Components является архитектурой по умолчанию для новых проектов Next.js начиная с версии 13, что означает, что затронуты большинство современных развертываний Next.js.

Любое приложение, использующее:

  • React Server Components с уязвимыми пакетами react-server-dom-* (19.0.0 - 19.2.0)
  • Next.js App Router версии 15.x (до 15.0.5) и 16.x (до 16.0.7)

Сюда входят производственные развертывания на Vercel, AWS, собственной инфраструктуре и везде, где работают приложения Next.js App Router.

Не подвержены влиянию:

  • Приложения Next.js Pages Router (без RSC)
  • Стабильные выпуски Next.js 13.x и 14.x
  • Приложения, использующие только клиентский рендеринг React
  • Развертывания Edge Runtime (нет process.mainModule)

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

React Server Components

ПакетУязвимаяИсправленная
react-server-dom-webpack19.0.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1+
react-server-dom-turbopack19.0.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1+
react-server-dom-parcel19.0.0, 19.1.0, 19.1.1, 19.2.019.0.1, 19.1.2, 19.2.1+

Next.js

ВерсияУязвимаяИсправленная
15.0.x< 15.0.515.0.5+
15.1.x< 15.1.915.1.9+
15.2.x< 15.2.615.2.6+
15.3.x< 15.3.615.3.6+
15.4.x< 15.4.815.4.8+
15.5.x< 15.5.715.5.7+
16.0.x< 16.0.716.0.7+

Смягчение

Обновляйтесь немедленно. Обходных путей нет.

Для приложений Next.js:

root@kitploit:~
npm install next@latest
# или
pnpm update next

Для прямого использования React RSC:

root@kitploit:~
npm install react-server-dom-webpack@latest

Проверьте установленные версии:

root@kitploit:~
npm ls next react-server-dom-webpack react-server-dom-turbopack

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

Требования к эксплойту

  1. Сервер, работающий на уязвимых React Server Components (через Next.js App Router или прямое использование RSC)
  2. Сетевой доступ для отправки HTTP POST-запроса
  3. И всё. Никакой аутентификации. Никакого конкретного конечного маршрута. Любой маршрут подходит.

Атака

Было обнаружено несколько векторов атаки для этой уязвимости. Наиболее распространенный - и тот, который работает без каких-либо предварительных условий - использует загрязнение прототипа через систему ссылок протокола Flight от React.

Эксплойт отправляет специально сформированный multipart POST-запрос с заголовком Next-Action. Полезная нагрузка злоупотребляет системой ссылок, чтобы:

  1. Пройтись по цепочке прототипов через $1:__proto__:then
  2. Создать поддельный объект "chunk", имитирующий внутренний класс Chunk React
  3. Обмануть десериализатор, вызвав конструктор JavaScript Function
  4. Выполнить произвольный код, когда результирующая функция вызывается как thenable Promise
root@kitploit:~
POST / HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----Boundary
Next-Action: x

------Boundary
Content-Disposition: form-data; name="0"

{"then":"$1:__proto__:then","status":"resolved_model","value":"{...}","_response":{...}}
------Boundary
Content-Disposition: form-data; name="1"

"$@0"
------Boundary--

Код выполняется во время десериализации, до того как произойдет проверка идентификатора действия. Это означает, что любое значение заголовка Next-Action вызывает уязвимый путь кода - никакой действительный идентификатор действия не требуется.

Существуют и другие векторы атаки, включая ссылки на функции $F и прямые модульные гаджеты. Обычно они требуют действительный ID действия. Подробнее см. в разделе Альтернативные векторы атаки.

Первопричина

Протокол Flight от React разрешает ссылки вида $1:path:to:value, разделяя их по двоеточиям и обходя объект:

root@kitploit:~
// ReactFlightReplyServer.js - getOutlinedModel()
for (let i = 1; i < path.length; i++) {
  value = value[path[i]];  // No hasOwnProperty check!
}

Ирония: В самом верху этого файла, строка 35:

root@kitploit:~
import hasOwnProperty from 'shared/hasOwnProperty';

Защита была импортирована. Она была доступна. Она просто не использовалась в том единственном цикле, где это было важнее всего.

Эта единственная отсутствующая проверка позволяет $1:__proto__:then пройти от объекта chunk вверх по цепочке прототипов к Chunk.prototype.then - функции, которая обрабатывает объекты, похожие на Promise. Создавая поддельный chunk с нужными свойствами, мы контролируем, какой код будет выполнен.

Локальное воспроизведение

Клонируйте уязвимый тестовый сервер:

root@kitploit:~
git clone https://github.com/freeqaz/react2shell
cd react2shell/vulnerable-next-server
pnpm install
pnpm dev

В другом терминале:

root@kitploit:~
./detect.sh http://localhost:3443

Уязвимый сервер возвращает HTTP 500 с E{"digest" в теле ответа. Чтобы продемонстрировать RCE:

root@kitploit:~
./exploit-redirect.sh http://localhost:3443 "id"

Вывод команды появляется в ответе. Для интерактивного исследования:

root@kitploit:~
./shell.sh http://localhost:3443

Что в этом репозитории

Уязвимый тестовый сервер

Директория vulnerable-next-server/ содержит предварительно настроенное приложение Next.js 16.0.6 + React 19.2.0 для безопасного локального тестирования. По умолчанию оно запускается на порту 3443. Это минимальная настройка App Router, демонстрирующая, что конфигурации по умолчанию уязвимы.

Скрипты эксплойтов

Мы разработали несколько вариантов эксплойта для разных сценариев:

СкриптHTTPВыводПродакшнПримечания
exploit-redirect.sh303x-action-redirect headerДаРекомендуется. Нет предварительных требований.
exploit-throw.sh500Error response bodyНетТолько режим разработки (ошибки очищаются в продакшне).
exploit-blind.sh200Server-side onlyДаFire-and-forget. Используйте для внеполосной эксфильтрации.
exploit-urlencoded.sh303x-action-redirect headerДаДругая сигнатура WAF. Требуется ID действия.
exploit-reflect.sh200Response bodyДаСамый скрытный. Требуется ID действия.

Примечание для продакшна: React удаляет сообщения об ошибках в производственных сборках, нарушая метод throw. Только exploit-redirect.sh надежно захватывает вывод команд в продакшне без предварительных требований. URL перенаправления сохраняется в свойстве digest (метаданные) ошибки, которое не очищается - в отличие от message, которое становится только {digest: "..."}.

Вспомогательные скрипты:

  • detect.sh - Неразрушающий зонд уязвимости (без выполнения кода)
  • enumerate-actions.sh - Обнаруживает действительные идентификаторы Server Action из целевого HTML
  • exfil-file.sh - Чанковая эксфильтрация файлов (автообработка больших файлов)
  • shell.sh - Интерактивная псевдо-оболочка поверх RCE

Метод перенаправления рекомендуется, потому что он работает в продакшне, не требует предварительных требований и возвращает вывод команды напрямую. Он работает путем выбрасывания специально созданной ошибки NEXT_REDIRECT - вывод кодируется в base64 в URL перенаправления и возвращается в заголовке x-action-redirect.

Подробное использование каждого скрипта см. в USAGE.md.

Как обнаружить уязвимые серверы

Быстрое обнаружение

root@kitploit:~
./detect.sh https://target.com

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

Ответ уязвимого сервера:

  • HTTP статус: 500
  • Content-Type: text/x-component
  • Тело содержит: E{"digest"

Исправленный или не-RSC сервер: Возвращает 404, другой формат ошибки или отсутствие ответа протокола Flight.

Ручное обнаружение

root@kitploit:~
curl -s -o /dev/null -w "%{http_code}" -X POST https://target.com \
  -H "Next-Action: x" \
  -H "Content-Type: multipart/form-data; boundary=----Boundary" \
  --data-binary $'------Boundary\r\nContent-Disposition: form-data; name="0"\r\n\r\n["$1:a:a"]\r\n------Boundary\r\nContent-Disposition: form-data; name="1"\r\n\r\n{}\r\n------Boundary--'

Этот зонд ссылается на несуществующее свойство пустого объекта. Уязвимые серверы аварийно завершают работу при попытке доступа к {}.a.a, возвращая 500. Исправленные серверы имеют защиту hasOwnProperty, предотвращающую сбой.

Идентификация Next.js App Router

Ищите эти признаки:

  • Полезная нагрузка RSC в HTML: теги <script>, содержащие данные протокола Flight (0:, 1: и т.д.)
  • Заголовки x-nextjs-cache или x-nextjs-matched-path
  • Пути статических ассетов /_next/
  • Идентификаторы действий сервера в HTML: шаблоны $ACTION_ID_ в скрытых полях форм

Техническое глубокое погружение

Поток атаки

Следующая диаграмма иллюстрирует, как один HTTP-запрос достигает удаленного выполнения кода:

root@kitploit:~
sequenceDiagram
    participant A as Attacker
    participant N as Next.js
    participant F as Flight Parser
    participant JS as JS Engine

    A->>N: POST with Next-Action header + malicious payload
    N->>F: Parse multipart form data
    F->>JS: await getRoot - returns chunk as thenable

    rect rgb(80, 20, 20)
        Note over F,JS: VULNERABILITY - No hasOwnProperty check
        JS->>F: chunk.then parses $1:__proto__:then
        F-->>F: Traverses to Chunk.prototype.then
    end

    F->>JS: resolve(attackerObject)
    Note over JS: JS Promise spec: resolve(thenable)<br/>calls thenable.then()
    JS->>F: fakeChunk.then() with attacker's _response

    rect rgb(80, 20, 20)
        Note over F,JS: EXPLOITATION - Attacker controls _response
        F->>F: $B0 → _formData.get(_prefix + "0")
        Note over F: _formData.get = Function constructor<br/>_prefix = malicious code string
        F->>JS: Function(code) invoked as thenable
    end

    Note over JS: RCE - execSync() runs

    rect rgb(20, 60, 20)
        Note over A,JS: OUTPUT EXFILTRATION (redirect method)
        JS-->>F: throw NEXT_REDIRECT with base64(output)
        F-->>N: Error propagates up
        N-->>A: HTTP 303 + x-action-redirect header
    end

Протокол Flight

React Server Components используют пользовательский формат сериализации под названием "Flight" для потоковой передачи деревьев компонентов с сервера на клиент. Он использует коды префиксов для разных типов значений:

  • $1, $2, ... - Ссылки на другие куски по ID
  • $@0 - Ссылка на необработанный объект chunk (возвращает сам chunk, а не его значение)
  • $B0 - Ссылка на Blob (запускает _formData.get(_prefix + id))
  • $1:path:to:prop - Обходит путь по значению ссылочного chunk

Уязвимость использует комбинацию $@ (необработанная ссылка) и путей, разделенных двоеточием, для доступа к __proto__.

Полная цепочка атаки

Фаза 1: Обработка запроса

  1. POST с заголовком Next-Action запускает обработку действия RSC
  2. Busboy разбирает multipart поля формы в хранилище chunk
  3. await getRoot(response) возвращает chunk 0 как thenable

Фаза 2: Обход прототипов

  1. Chunk имеет метод then - спецификация JS Promise вызывает thenable.then(resolve, reject)
  2. Наша полезная нагрузка анализируется; $1:__proto__:then разрешается в Chunk.prototype.then
  3. Создается поддельный объект chunk с then, status: "resolved_model" и _response

Фаза 3: Выполнение кода

  1. resolve(ourObject) запускает еще один вызов then() (спецификация thenable JS)
  2. Chunk.prototype.then выполняется, используя наш управляемый объект _response
  3. $B0 запускает _formData.get(_prefix + "0") - оба контролируются злоумышленником
  4. Созданная Function вызывается как thenable → RCE

Фаза 4: Эксфильтрация вывода (опционально, метод перенаправления)

  1. Полезная нагрузка выбрасывает ошибку NEXT_REDIRECT с base64-закодированным выводом команды
  2. Next.js перехватывает перенаправление, устанавливает заголовок x-action-redirect до проверки URL
  3. HTTP 303 возвращается атакующему с выводом в заголовке

Стратегии захвата вывода

Созданная Function вызывается как thenable: fn(resolve, reject). То, как мы это обрабатываем, определяет, получим ли мы вывод обратно:

СтратегияСуффикс полезной нагрузкиКак это работает
BlindexecSync('CMD');0Выполняется, но никогда не разрешается - соединение зависает, вывода нет
Throwthrow execSync('CMD').toString()Отклоняет Promise, вывод в теле ошибки (только режим разработки)
Redirectthrow {digest:'NEXT_REDIRECT;...;'+b64(output)}Злоупотребляет обработкой перенаправления Next.js, вывод в заголовке
Reflectarguments[0](https://github.com/freeqaz/react2shell/blob/master/%5BexecSync%28%27CMD%27).toString()])Разрешает Promise с выводом в качестве аргумента действия (требует действительный ID действия)

Рекомендуется: Redirect. Работает в продакшне, без предварительных требований, вывод в заголовке x-action-redirect.

Подход blind зависает, потому что Promise никогда не завершается - await блокируется навсегда. Это полезно для сценариев fire-and-forget (обратные шеллы, внеполосная эксфильтрация через curl).

Альтернативные векторы атаки

Основная уязвимость была использована через три различных класса атак. Этот репозиторий использует первый подход; другие PoC демонстрируют альтернативы:

Класс атакиМеханизмТребуется ID действияПример PoC
Prototype PollutionОбход $1:__proto__:then к Chunk.prototypeНетreact2shell, lachlan2k, joe-desimone
$F Function Reference$F1 + action#constructor для достижения FunctionДаshellinteractive
Module GadgetСинтаксис module#export (например, child_process#execSync)Зависитejpir research

Почему загрязнение прототипа не требует ID действия: Разбор multipart формы сразу передает chunk десериализатору Flight. RCE происходит в getOutlinedModel() во время разрешения ссылки chunk - до того, как Next.js проверит ID действия. URL-закодированные запросы сначала проверяют ID действия (другой путь кода в action-handler.ts:768).

Почему ссылка $F требует ID действия: Ссылка $F запускает loadServerReference(), которая выполняет поиск в манифесте. Если действие не существует, запрос завершается ошибкой до выполнения кода.

Подробный анализ всех реализаций PoC и их компромиссов см. в external-pocs/COMPARISON.md.

Продакшн и разработка

React удаляет детали ошибок в производственных сборках. Это влияет на эксфильтрацию на основе throw:

Разработка:

root@kitploit:~
{"digest":"...","name":"Error","message":"uid=501(free)...","stack":[...]}

Продакшн:

root@kitploit:~
{"digest":"..."}

Метод перенаправления обходит это, потому что URL перенаправления хранится в свойстве digest, а не в message. Заголовок устанавливается безусловно до проверки URL, поэтому даже недействительные URL получают заголовок.

Благодарности

Ключевое открытие эксплуатации - использование необработанных ссылок $@ для создания самореферентного поддельного chunk - приписывается maple3142. Методология обнаружения, на которую здесь ссылаются, исходит от Searchlight Cyber / Assetnote.

Ссылки

Официальные раскрытия:

  • CVE-2025-55182 - RCE в React Server Components
  • CVE-2025-66478 - Влияние на Next.js
  • Предупреждение безопасности React - Официальное раскрытие React

Исследования сообщества:

АвторВкладПуть атакиПримечательные особенности
lachlan2kПервооткрывательЗагрязнение прототипаОбъединение Array.map, структура из 5 chunk, поддержка Waku
ejpirИсследование гаджетовВсе путиКаталог модульных гаджетов, атаки на постоянство, пути data URI
joe-desimoneИнструментарий на PythonЗагрязнение прототипаПомощник обратного шелла, эксфильтрация через callback, обнаружение таймаута
labubusDest / MrR0b0t19Интерактивная оболочкаСсылка на функцию $FPython REPL, загрузка/скачивание файлов, встроенный набор тестов
Searchlight CyberМетоды обнаружения—Методология обнаружения высокой точности, сигнатуры WAF

Подробное сравнение всех реализаций PoC см. в external-pocs/COMPARISON.md.

Предыстория:

  • Протокол Flight React - Понимание сериализации RSC

Лицензия

Код лицензирован под MIT License. Документация (*.md файлы) лицензирована под CC-BY-SA 4.0.

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