
Углубленный анализ и PoC для CVE-2025-29927, обход авторизации промежуточного слоя Next.js через заголовок x-middleware-subrequest. Включает шаблоны Nuclei и скрипт массового сканирования для тестирования.
В данном документе представлено исследование уязвимости CVE-2025-29927, затрагивающей механизм Middleware во фреймворке Next.js.
Next.js — популярный open-source фреймворк от Vercel для разработки приложений на базе React. Он поддерживает серверный рендеринг, статическую генерацию и гибкую систему промежуточного ПО (middleware), применяемую для маршрутизации, перенаправлений, заголовков безопасности и проверки прав доступа.
В марте 2025 года была выявлена критическая уязвимость CVE-2025-29927, связанная с обработкой служебного заголовка внутренних подзапросов.
Суть проблемы — возможность обойти авторизационные проверки в приложениях, где контроль доступа реализован именно в middleware, путём подстановки особого значения в HTTP-заголовок x-middleware-subrequest. Если безопасность завязана только на middleware, злоумышленник может получить доступ к закрытым маршрутам или данным.
Затронутые версии Next.js и исправления (по публичным источникам и официальным материалам):
Исправления доступны в релизах 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3.
Next.js широко применяется в продакшне; уязвимость, задевающая слой middleware (часто используемый для аутентификации/авторизации и политики безопасности), несёт высокий практический риск.
Пошагово разобрать уязвимость и оформить полный цикл исследования:
Сбор и структурирование материалов.
Систематизировать публичные источники по CVE-2025-29927; изложить суть дефекта, условия срабатывания и подтверждённые версии/патчи.
Определение CPE и условий конфигурации.
Привести список CPE/версий и описать конфигурации, при которых уязвимость воспроизводится (например, self-hosted деплой и авторизация на уровне middleware).
Безопасная демонстрация.
Подготовить воспроизводимое демо на тестовой среде (без деструктивных действий), подтверждающее факт обхода middleware в уязвимых версиях.
Методики массовой проверки.
Описать и реализовать три безопасных подхода:

Первопричина. В Next.js служебный заголовок x-middleware-subrequest используется для отслеживания внутренних подзапросов и предотвращения рекурсии в middleware. В уязвимых ветках внешние клиенты могут подставить этот заголовок с «ожидаемым» значением — и рантайм пропускает выполнение middleware, передавая запрос напрямую обработчику маршрута.
Роль заголовка. Сам заголовок x-middleware-subrequest изначально задумывался как внутренний индикатор того, что текущий HTTP-запрос запущен самим фреймворком как промежуточный подзапрос, а не пришёл напрямую от пользователя.
Он нужен для корректной работы внутренних механизмов Next.js: помимо маршрутизации, этот флаг помогает избежать бесконечной рекурсии, «отмечая» каждый вызванный промежуточный слой.
Но именно эта логика породила непреднамеренную дыру в защите: клиент, самостоятельно добавивший такой заголовок, может заставить систему трактовать свой запрос как внутренний и тем самым миновать авторизационные проверки.
Эволюция логики.
Актуальные записи NVD указывают на продукт Vercel Next.js с целевым ПО node.js. Для уязвимых веток применяются следующие конфигурации (диапазоны версий заданы на уровне CPE-конфигураций в NVD):
| CPE URI | Уязвимый диапазон версий |
|---|---|
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 11.1.4 ≤ v < 12.3.5 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 13.0.0 ≤ v < 13.5.9 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 14.0.0 ≤ v < 14.2.25 |
cpe:2.3:a:vercel:next.js:*:*:*:*:*:node.js:*:* | 15.0.0 ≤ v < 15.2.3 |
Примечание: в описании CVE также указывается, что в целом «начиная с 11.1.4 и до 12.3.5 / 13.5.9 / 14.2.25 / 15.2.3» уязвимость воспроизводится при выполнении условий ниже.
next start, сборка с output: 'standalone') или любая среда, где middleware исполняется на входящих запросах без периметровой фильтрации служебных заголовков.x-middleware-subrequest (например, правила WAF).x-middleware-subrequestЧтобы исключить бесконечную рекурсию промежуточного кода, рантайм формирует и читает служебный заголовок:
: — получается массив «подзапросов».NextResponse.next()),x-middleware-subrequest-id), связанный с текущей сессией процесса; если он не совпадает, входящий x-middleware-subrequest очищается на серверной стороне.Злоумышленник посылает HTTP-запрос в целевое Next.js-приложение, добавляя в него служебный заголовок x-middleware-subrequest.
В значении указывается путь до файла middleware — например pages/_middleware, middleware или src/middleware.
Нужное значение зависит от используемой версии Next.js и от структуры проекта.
Когда такой запрос достигает приложения, внутренняя логика фреймворка воспринимает его как внутренний подзапрос и предполагает, что промежуточный слой уже был выполнен.
В результате проверки аутентификации и авторизации, которые обычно происходят в middleware, фактически пропускаются.
Важно: данный материал приведён исключительно для проверки патча и моделирования риска в закрытой тестовой среде.
Любые проверки в продуктивной инфраструктуре возможны только с разрешения владельца ресурсов.
Next.js использует служебный заголовок x-middleware-subrequest, чтобы отмечать внутренние подзапросы и предотвращать рекурсивный запуск middleware.
При обработке запроса значение заголовка разбивается по символу : и сравнивается с именем текущего middleware.
В новых версиях добавлен лимит глубины (MAX_RECURSION_DEPTH, обычно 5).
Если условие (совпадение имени или достижение лимита) выполняется, Next.js пропускает middleware и передаёт запрос дальше.
Атакующий может сформировать корректное значение заголовка, имитируя внутренний подзапрос.