Недавно я и Яссер Аллам, известный под псевдонимом inzo_, решили объединить усилия для проведения исследования. Обсудив несколько потенциальных целей, мы решили сосредоточиться на Next.js (на GitHub у него 130 000 звезд, а еженедельные загрузки превышают 9,4 миллиона). Это фреймворк, с которым я очень хорошо знаком и с которым у меня есть прекрасный опыт работы, как это подтверждают мои предыдущие исследования. Таким образом, в данной статье «мы» естественно относится к нам двоим.
Next.js — это полноценный JavaScript фреймворк на основе React, обладающий множеством функций — идеальное место для глубокого изучения деталей. С верой, любопытством и упорством мы отправляемся в путешествие, исследуя малоизвестные уголки в поисках сокровищ, скрывающихся в них.
Скоро после этого мы обнаружили серьезную проблему в промежуточном ПО. Она имеет широкий масштаб воздействия, все версии подвержены этой проблеме, и для использования этого уязвимости не требуется никаких предварительных условий — мы скоро предоставим подробную информацию.
Содержание
Next.js Промежуточное ПО
Инструмент авторизации: код старого уровня сокровищ
Порядок выполнения и middlewareInfo.name
Инструмент авторизации: вчера стал стихом, сегодня еще более ценен
/src каталог
Максимальная глубина рекурсии
эксплуатация уязвимостей
Обойти авторизацию/перезаписать
Обойти CSP
Атака DoS с использованием отравления кэша (Что?)
разъяснение
Безопасностное уведомление - CVE-2025-29927
Отказ от ответственности
Заключение
Промежуточное ПО Next.js
Промежуточное программное обеспечение позволяет вам выполнять код до завершения запроса. Затем вы можете изменить содержание ответа, в зависимости от входящего запроса, переопределяя, перенаправляя, изменяя запрос или заголовки ответа, или напрямую возвращая ответ (из документации Next.js).
В качестве полноценной платформы Next.js имеет свои собственные промежуточные программы (middleware) — это важная и широко используемая функция. У нее множество областей применения, среди которых наиболее важные включают:
Перезапись пути (Path rewriting)
Серверные перенаправления (Server-side redirects)
Добавьте заголовки (например, CSP и др.) в ответ
Самое важное: аутентификация (Authentication) и авторизация (Authorization)
Одно из распространенных применений посредника — это авторизация, которая включает защиту определенных путей на основе конкретных условий.
Аутентификация и авторизация: перед предоставлением доступа к определенной странице или маршруту API убедитесь в идентификации пользователя и проверьте cookie сессии (документация Next.js).
Пример: Когда пользователь пытается получить доступ к /dashboard/admin, запрос сначала проходит через промежуточное ПО, которое проверяет, действителен ли сеанс cookie пользователя и есть ли у него необходимые разрешения. Если проверка проходит, промежуточное ПО перенаправляет запрос; в противном случае промежуточное ПО перенаправляет пользователя на страницу входа:
Инструмент авторизации: код старой версии уровня сокровища
Как сказал великий человек: «говорить легко, покажите мне ошибку», давайте избегать излишних рассказов и перейдем к делу; при просмотре старой версии фрейма (v12.0.7) мы обнаружили этот код:
Когда приложение Next.js использует ПО промежуточного слоя, вызывается функция runMiddleware. В дополнение к своей основной функции, функция принимает значение заголовка x-middleware-subrequest и использует его для определения того, следует ли применять промежуточное ПО. Значение заголовка разбивается на список с помощью двоеточия (:) в качестве разделителя, и список проверяется, содержит ли он значение middlewareInfo.name. Это означает, что если мы добавим в запрос заголовок x-middleware-subrequest с правильным значением, то промежуточное ПО – независимо от его назначения – будет полностью проигнорировано и запрос будет перенаправлен через NextResponse.next() и путь к исходному назначению будет завершен без какого-либо влияния со стороны промежуточного ПО. Эта голова и ее значение подобны «мастер-ключу», который обходит все правила. В этот момент мы поняли, что нашли удивительную проблему, и последние несколько кусочков головоломки должны быть завершены дальше.
Чтобы наша «универсальная ключ» заработала, её значение должно содержать middlewareInfo.name, но что это за значение?
Порядок выполнения и middlewareInfo.name
Значение middlewareInfo.name очень легко угадать, это просто путь, где находится промежуточное программное обеспечение. Чтобы понять это, нам нужно немного узнать о способе конфигурации промежуточного программного обеспечения в старых версиях.
Сначала, до версии 12.2 — в этой версии произошло изменение соглашения о промежуточном программном обеспечении — файлы должны называться _middleware.ts. Кроме того, маршрутизатор приложения (router) был введен только в версии 13 Next.js. Единственным существовавшим маршрутизатором на тот момент был маршрутизатор страниц, поэтому этот файл должен находиться в папке pages (специфично для маршрутизатора).
Имея эту информацию, мы можем сделать вывод о точном пути промежуточного ПО, а также предположить значение заголовка x-middleware-subrequest. Это значение состоит только из имени каталога (то есть единственного имени маршрутизатора, существовавшего в то время) и имени файла, следуя соглашению о наименовании, начинающемуся с нижнего подчеркивания:
x-middleware-subrequest: pages/_middleware
Когда мы пытаемся обойти те промежуточные программы, которые настроены на систематическую переадресацию попыток доступа с /dashboard/team/admin на /dashboard:
Успех, мы вторглись ⚔️
Теперь мы можем полностью обойти промежуточное ПО, обходя любые системы защиты, основанные на нем, наиболее типичным примером является авторизация, как в нашем приведенном выше примере. Это открытие довольно удивительно, но есть и другие моменты, которые следует учитывать.
Версии до 12.2 позволяли размещать один или несколько _middleware файлов на любом уровне дерева каталогов (начиная с папки pages), и у них был порядок выполнения, как мы видели на старых скриншотах документов, полученных из Web Archive:
Это что значит для нашей эксплуатации уязвимостей?
Вероятность = количество уровней на пути
Таким образом, чтобы получить доступ к /dashboard/panel/admin (защищенному посредником), значение middlewareInfo.name может иметь три возможных варианта, соответственно значение x-middleware-subrequest также может иметь три возможных варианта:
страниц/_middleware
или
pages/dashboard/_middleware
или
страницы/панель мониторинга/панель/_middleware
Инструмент авторизации: вчера стал стихом, сегодня еще более ценен
На данный момент мы считаем, что уязвимы только версии до 13, так как промежуточное программное обеспечение было перемещено в исходный код, и мы еще не охватили все его аспекты. Мы предполагаем, что поддерживающие разработчики, должно быть, уже заметили эту уязвимость и исправили ее до значительных изменений в версии 13, поэтому мы сообщили об этой уязвимости разработчикам фреймворка и продолжили наше исследование.
Что нас очень удивило, так это то, что через два дня после первоначального обнаружения мы выяснили, что все версии Next.js — начиная с версии 11.1.4 — имеют уязвимость! Код больше не находится в одном и том же месте, а логика эксплуатации немного изменилась.
Как упоминалось ранее, начиная с версии 12.2, файл больше не содержит подчеркивания и должен быть просто назван middleware.ts. Кроме того, он больше не находится в папке pages (что удобно для нас, поскольку начиная с версии 13 был введен маршрутизатор приложения, что удвоило бы возможности).
С учетом этого, полезная нагрузка для первых версий, начиная с версии 12.2, очень проста:
Учитывая это, первый релиз версии 12.2 имеет очень простой полезный нагруз.
x-middleware-subrequest: промежуточное ПО
/src каталог
Также следует учитывать, что Next.js предоставляет возможность создания каталога /src:
(Next.js documentation) В качестве альтернативы специальному каталогу Next.js app или pages в корневом каталоге проекта Next.js также поддерживает распространенный шаблон размещения кода приложения в каталоге src. (Next.js док)
В этом случае полезная нагрузка будет следующей:
x-middleware-subrequest: src/middleware
Таким образом, независимо от того, сколько уровней в пути, существует только две возможности. Это упрощает сложность эксплуатации уязвимостей для соответствующих версий.
В последней версии произошли небольшие изменения (мы гарантируем, что это в последний раз).
Максимальная глубина рекурсии
В обновленной версии логика немного изменилась, посмотрите этот фрагмент кода:
Версия 15.1.7
Как и прежде, система будет извлекать значение заголовка x-middleware-subrequest и формировать список, используя двоеточие в качестве разделителя. Но на этот раз условия для непосредственной пересылки запроса — то есть игнорирование правил промежуточного программного обеспечения — будут отличаться:
Значение константы depth должно быть больше или равно значению константы MAX_RECURSION_DEPTH (то есть 5). В процессе присваивания каждый раз, когда какое-либо значение в списке subrequests (то есть в заголовке, разделенном :) равно params.name (то есть пути к среднему программному обеспечению), константа depth увеличивается на 1. Как уже упоминалось, здесь есть только два варианта: middleware или src/middleware.
Таким образом, чтобы обойти промежуточное программное обеспечение, нам нужно просто добавить следующие заголовки/значения в запрос:
Этот код, похоже, предназначен для предотвращения зацикливания рекурсивных запросов.
эксплуатация уязвимостей
Поскольку мы знаем, что вам нравится такой контент, вот несколько реальных примеров из программы Bug Bounty.
Обойти авторизацию/перезаписать
В этом примере, когда мы пытаемся получить доступ к /admin/login, мы получаем ответ 404. Из заголовков ответа видно, что посредник выполнил переработку пути, чтобы предотвратить доступ несанкционированных или неподобающих пользователей:
Но используя наш авторизованный артефакт :
Мы можем беспрепятственно получить доступ к этой конечной точке, промежуточное ПО полностью игнорируется. Целевая версия Next.js: 15.1.7
Обойти CSP
На этот раз сайт использует промежуточное программное обеспечение для настройки, среди прочего, CSP и файлов cookie:
Давайте обойдём это:
Целевая версия next.js: 15.0.3Целевая версия next.js: 15.0.3
Обратите внимание: обратите внимание на различия в полезной нагрузке двух целей, одна из которых использует каталог src/, а другая - нет.
Атака DoS с использованием отравления кэша (Что?)
Да, через этот уязвимость также может быть осуществлена атака DoS с отравлением кэша. Это явно не то, что мы ищем в первую очередь, но если нет защищенных чувствительных путей и нет более интересных точек для эксплуатации, то в некоторых случаях это может привести к отказу в обслуживании отравлением кэша (CPDoS):
Предположим, что сайт переписывает путь пользователя в зависимости от его географического положения, добавляя (/en, /fr и т.д.), и не предоставляет страницы или ресурсы по корневому пути (/). Если мы обойдем промежуточное ПО, то сможем избежать переписывания и в конечном итоге попасть на корневую страницу. Поскольку разработчик не планировал разрешать пользователям доступ к корневой странице, соответствующая страница не была предоставлена, и мы получим 404 (или, в зависимости от конфигурации/типа переписывания, возможно, 500).
Если сайт использует кэширование/CDN систему, это может принудительно кэшировать 404 ответ, что приведет к недоступности страницы и серьезно повлияет на доступность сайта.
разъяснение
С момента публикации уведомления о безопасности мы получили несколько запросов от людей, которые беспокоятся о безопасности своих приложений и не совсем понимают масштаб атаки. Необходимо уточнить, что уязвимым элементом является промежуточное ПО. Если вы не используете промежуточное ПО (или, по крайней мере, не используете его для чувствительных целей), то не о чем беспокоиться (хотя проверьте упомянутые выше аспекты DoS), потому что обход промежуточного ПО не обходит никакие реальные механизмы безопасности.
В противном случае последствия могут быть катастрофическими, мы рекомендуем вам быстро внедрить меры, указанные в уведомлении о безопасности.
Безопасностное уведомление - CVE-2025-29927
патч
Для Next.js 15.x эта проблема была исправлена в версии 15.2.3
Для Next.js 14.x эта проблема была исправлена в версии 14.2.25
Для версий Next.js от 11.1.4 до 13.5.6 мы рекомендуем ознакомиться со следующими решениями.
Решение
Если вы не можете обновиться до безопасной версии, мы рекомендуем вам заблокировать доступ внешних пользовательских запросов с заголовком запроса x-middleware-subrequest к вашему приложению Next.js.
На момент написания этой статьи приложения, развернутые на Vercel и Netlify, очевидно, больше не подвержены этой уязвимости (обновление: из-за большого количества ложных срабатываний Cloudflare изменил это правило так, чтобы оно действовало только при активном включении пользователем — эти ложные срабатывания не смогли эффективно различить запросы от законных пользователей и потенциальных злоумышленников).
Отказ от ответственности
Данное исследование публикуется исключительно в образовательных целях и предназначено для помощи разработчикам в понимании коренных причин проблемы или для предоставления вдохновения исследователям / охотникам за уязвимостями в их будущей исследовательской деятельности. Эта статья является дополнительным материалом к уведомлению о безопасности, в которой содержится дальнейшее объяснение и уточнение природы уязвимости — поскольку в уведомлении уже были опубликованы заголовки запросов, которые привели к данной уязвимости (а также соответствующие различия в отправках).
Мы явно заявляем, что не поддерживаем какое-либо неэтичное использование данного текста.
Заключение
Как подчеркивается в этой статье, этот уязвимость существует в исходном коде Next.js уже несколько лет и изменяется вместе с эволюцией промежуточного программного обеспечения и его версий. Любое программное обеспечение может иметь серьезные уязвимости, но когда это затрагивает один из самых популярных фреймворков, это становится особенно опасным и может иметь серьезные последствия для более широкой экосистемы. Как уже упоминалось, на момент написания этой статьи Next.js загружается почти 10 миллионов раз в неделю. Он широко используется в таких критически важных областях, как банковские услуги и блокчейн. Когда уязвимость затрагивает зрелые функции, на которые полагаются пользователи (такие как авторизация и аутентификация), риск увеличивается.
Команда Vercel потратила несколько дней на исправление этой уязвимости, но стоит отметить, что, как только они осознали проблему, исправление было подано и объединено в новую версию всего за несколько часов (включая обратную портировку).
Временная линия :
27 февраля 2025 года: сообщено о уязвимости разработчикам (на тот момент мы полагали, что только версии с 12.0.0 по 12.0.7 затронуты, и указали это в отчете).
1 марта 2025 года: отправлено второе письмо, в котором говорится, что на самом деле все версии имеют уязвимости, включая последнюю стабильную версию.
5 марта 2025 года: получен предварительный ответ от команды Vercel, в котором сообщается, что версия 12.x больше не поддерживается (возможно, они еще не прочитали приложенный к нашему второму письму шаблон объявления о безопасности и не обратили внимания на то, что все версии подвержены риску).
5 марта 2025 года: повторно отправляю письмо, пожалуйста, команда, как можно скорее ознакомьтесь со вторым письмом и шаблоном уведомления о безопасности.
11 марта 2025 года: повторно отправить письмо, подтвердить, была ли принята новая информация.
17 марта 2025 года: получен ответ от команды Vercel, подтверждающий, что соответствующая информация принята к сведению.
18 марта 2025 года: получено письмо от команды Vercel, в котором сообщается, что отчет принят, патч исправления завершен. Через несколько часов вышла версия 15.2.3 с исправлениями (включая исправления обратной совместимости).
21 марта 2025 года: Официальное объявление о безопасности.
В общем, процесс поиска нулевых уязвимостей становится захватывающим и адреналиновым только в тот момент, когда обнаруживается зацепка; остальное время — это путешествие, полное неопределенности — для любопытствующих оно приносит знания; для тех, кто не терпит ждать, это путешествие кажется особенно долгим. Не сомневайтесь, действовать в команде гораздо легче, чем пересекать пустыню в одиночку.
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
Уязвимость Next.js и промежуточного ПО: неверные механизмы авторизации
Автор: Rachid.A
Перевод: Yewlne
01 Текст перевода
Недавно я и Яссер Аллам, известный под псевдонимом inzo_, решили объединить усилия для проведения исследования. Обсудив несколько потенциальных целей, мы решили сосредоточиться на Next.js (на GitHub у него 130 000 звезд, а еженедельные загрузки превышают 9,4 миллиона). Это фреймворк, с которым я очень хорошо знаком и с которым у меня есть прекрасный опыт работы, как это подтверждают мои предыдущие исследования. Таким образом, в данной статье «мы» естественно относится к нам двоим.
Next.js — это полноценный JavaScript фреймворк на основе React, обладающий множеством функций — идеальное место для глубокого изучения деталей. С верой, любопытством и упорством мы отправляемся в путешествие, исследуя малоизвестные уголки в поисках сокровищ, скрывающихся в них.
Скоро после этого мы обнаружили серьезную проблему в промежуточном ПО. Она имеет широкий масштаб воздействия, все версии подвержены этой проблеме, и для использования этого уязвимости не требуется никаких предварительных условий — мы скоро предоставим подробную информацию.
Содержание
Next.js Промежуточное ПО
Инструмент авторизации: код старого уровня сокровищ
Порядок выполнения и middlewareInfo.name
Инструмент авторизации: вчера стал стихом, сегодня еще более ценен
/src каталог
Максимальная глубина рекурсии
эксплуатация уязвимостей
Обойти авторизацию/перезаписать
Обойти CSP
Атака DoS с использованием отравления кэша (Что?)
разъяснение
Безопасностное уведомление - CVE-2025-29927
Отказ от ответственности
Заключение
Промежуточное ПО Next.js
Промежуточное программное обеспечение позволяет вам выполнять код до завершения запроса. Затем вы можете изменить содержание ответа, в зависимости от входящего запроса, переопределяя, перенаправляя, изменяя запрос или заголовки ответа, или напрямую возвращая ответ (из документации Next.js).
В качестве полноценной платформы Next.js имеет свои собственные промежуточные программы (middleware) — это важная и широко используемая функция. У нее множество областей применения, среди которых наиболее важные включают:
Перезапись пути (Path rewriting)
Серверные перенаправления (Server-side redirects)
Добавьте заголовки (например, CSP и др.) в ответ
Самое важное: аутентификация (Authentication) и авторизация (Authorization)
Одно из распространенных применений посредника — это авторизация, которая включает защиту определенных путей на основе конкретных условий.
Аутентификация и авторизация: перед предоставлением доступа к определенной странице или маршруту API убедитесь в идентификации пользователя и проверьте cookie сессии (документация Next.js).
Пример: Когда пользователь пытается получить доступ к /dashboard/admin, запрос сначала проходит через промежуточное ПО, которое проверяет, действителен ли сеанс cookie пользователя и есть ли у него необходимые разрешения. Если проверка проходит, промежуточное ПО перенаправляет запрос; в противном случае промежуточное ПО перенаправляет пользователя на страницу входа:
Инструмент авторизации: код старой версии уровня сокровища
Как сказал великий человек: «говорить легко, покажите мне ошибку», давайте избегать излишних рассказов и перейдем к делу; при просмотре старой версии фрейма (v12.0.7) мы обнаружили этот код:
Когда приложение Next.js использует ПО промежуточного слоя, вызывается функция runMiddleware. В дополнение к своей основной функции, функция принимает значение заголовка x-middleware-subrequest и использует его для определения того, следует ли применять промежуточное ПО. Значение заголовка разбивается на список с помощью двоеточия (:) в качестве разделителя, и список проверяется, содержит ли он значение middlewareInfo.name. Это означает, что если мы добавим в запрос заголовок x-middleware-subrequest с правильным значением, то промежуточное ПО – независимо от его назначения – будет полностью проигнорировано и запрос будет перенаправлен через NextResponse.next() и путь к исходному назначению будет завершен без какого-либо влияния со стороны промежуточного ПО. Эта голова и ее значение подобны «мастер-ключу», который обходит все правила. В этот момент мы поняли, что нашли удивительную проблему, и последние несколько кусочков головоломки должны быть завершены дальше.
Чтобы наша «универсальная ключ» заработала, её значение должно содержать middlewareInfo.name, но что это за значение?
Порядок выполнения и middlewareInfo.name
Значение middlewareInfo.name очень легко угадать, это просто путь, где находится промежуточное программное обеспечение. Чтобы понять это, нам нужно немного узнать о способе конфигурации промежуточного программного обеспечения в старых версиях.
Сначала, до версии 12.2 — в этой версии произошло изменение соглашения о промежуточном программном обеспечении — файлы должны называться _middleware.ts. Кроме того, маршрутизатор приложения (router) был введен только в версии 13 Next.js. Единственным существовавшим маршрутизатором на тот момент был маршрутизатор страниц, поэтому этот файл должен находиться в папке pages (специфично для маршрутизатора).
Имея эту информацию, мы можем сделать вывод о точном пути промежуточного ПО, а также предположить значение заголовка x-middleware-subrequest. Это значение состоит только из имени каталога (то есть единственного имени маршрутизатора, существовавшего в то время) и имени файла, следуя соглашению о наименовании, начинающемуся с нижнего подчеркивания:
x-middleware-subrequest: pages/_middleware
Когда мы пытаемся обойти те промежуточные программы, которые настроены на систематическую переадресацию попыток доступа с /dashboard/team/admin на /dashboard:
Успех, мы вторглись ⚔️
Теперь мы можем полностью обойти промежуточное ПО, обходя любые системы защиты, основанные на нем, наиболее типичным примером является авторизация, как в нашем приведенном выше примере. Это открытие довольно удивительно, но есть и другие моменты, которые следует учитывать.
Версии до 12.2 позволяли размещать один или несколько _middleware файлов на любом уровне дерева каталогов (начиная с папки pages), и у них был порядок выполнения, как мы видели на старых скриншотах документов, полученных из Web Archive:
Это что значит для нашей эксплуатации уязвимостей?
Вероятность = количество уровней на пути
Таким образом, чтобы получить доступ к /dashboard/panel/admin (защищенному посредником), значение middlewareInfo.name может иметь три возможных варианта, соответственно значение x-middleware-subrequest также может иметь три возможных варианта:
страниц/_middleware
или
pages/dashboard/_middleware
или
страницы/панель мониторинга/панель/_middleware
Инструмент авторизации: вчера стал стихом, сегодня еще более ценен
На данный момент мы считаем, что уязвимы только версии до 13, так как промежуточное программное обеспечение было перемещено в исходный код, и мы еще не охватили все его аспекты. Мы предполагаем, что поддерживающие разработчики, должно быть, уже заметили эту уязвимость и исправили ее до значительных изменений в версии 13, поэтому мы сообщили об этой уязвимости разработчикам фреймворка и продолжили наше исследование.
Что нас очень удивило, так это то, что через два дня после первоначального обнаружения мы выяснили, что все версии Next.js — начиная с версии 11.1.4 — имеют уязвимость! Код больше не находится в одном и том же месте, а логика эксплуатации немного изменилась.
Как упоминалось ранее, начиная с версии 12.2, файл больше не содержит подчеркивания и должен быть просто назван middleware.ts. Кроме того, он больше не находится в папке pages (что удобно для нас, поскольку начиная с версии 13 был введен маршрутизатор приложения, что удвоило бы возможности).
С учетом этого, полезная нагрузка для первых версий, начиная с версии 12.2, очень проста:
Учитывая это, первый релиз версии 12.2 имеет очень простой полезный нагруз.
x-middleware-subrequest: промежуточное ПО
/src каталог
Также следует учитывать, что Next.js предоставляет возможность создания каталога /src:
(Next.js documentation) В качестве альтернативы специальному каталогу Next.js app или pages в корневом каталоге проекта Next.js также поддерживает распространенный шаблон размещения кода приложения в каталоге src. (Next.js док)
В этом случае полезная нагрузка будет следующей:
x-middleware-subrequest: src/middleware
Таким образом, независимо от того, сколько уровней в пути, существует только две возможности. Это упрощает сложность эксплуатации уязвимостей для соответствующих версий.
В последней версии произошли небольшие изменения (мы гарантируем, что это в последний раз).
Максимальная глубина рекурсии
В обновленной версии логика немного изменилась, посмотрите этот фрагмент кода:
Версия 15.1.7
Как и прежде, система будет извлекать значение заголовка x-middleware-subrequest и формировать список, используя двоеточие в качестве разделителя. Но на этот раз условия для непосредственной пересылки запроса — то есть игнорирование правил промежуточного программного обеспечения — будут отличаться:
Значение константы depth должно быть больше или равно значению константы MAX_RECURSION_DEPTH (то есть 5). В процессе присваивания каждый раз, когда какое-либо значение в списке subrequests (то есть в заголовке, разделенном :) равно params.name (то есть пути к среднему программному обеспечению), константа depth увеличивается на 1. Как уже упоминалось, здесь есть только два варианта: middleware или src/middleware.
Таким образом, чтобы обойти промежуточное программное обеспечение, нам нужно просто добавить следующие заголовки/значения в запрос:
x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware:middleware:middleware
или
x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware:src/middleware
Для чего изначально предназначен этот код?
Этот код, похоже, предназначен для предотвращения зацикливания рекурсивных запросов.
эксплуатация уязвимостей
Поскольку мы знаем, что вам нравится такой контент, вот несколько реальных примеров из программы Bug Bounty.
Обойти авторизацию/перезаписать
В этом примере, когда мы пытаемся получить доступ к /admin/login, мы получаем ответ 404. Из заголовков ответа видно, что посредник выполнил переработку пути, чтобы предотвратить доступ несанкционированных или неподобающих пользователей:
Но используя наш авторизованный артефакт :
Мы можем беспрепятственно получить доступ к этой конечной точке, промежуточное ПО полностью игнорируется. Целевая версия Next.js: 15.1.7
Обойти CSP
На этот раз сайт использует промежуточное программное обеспечение для настройки, среди прочего, CSP и файлов cookie:
Давайте обойдём это:
Целевая версия next.js: 15.0.3Целевая версия next.js: 15.0.3
Обратите внимание: обратите внимание на различия в полезной нагрузке двух целей, одна из которых использует каталог src/, а другая - нет.
Атака DoS с использованием отравления кэша (Что?)
Да, через этот уязвимость также может быть осуществлена атака DoS с отравлением кэша. Это явно не то, что мы ищем в первую очередь, но если нет защищенных чувствительных путей и нет более интересных точек для эксплуатации, то в некоторых случаях это может привести к отказу в обслуживании отравлением кэша (CPDoS):
Предположим, что сайт переписывает путь пользователя в зависимости от его географического положения, добавляя (/en, /fr и т.д.), и не предоставляет страницы или ресурсы по корневому пути (/). Если мы обойдем промежуточное ПО, то сможем избежать переписывания и в конечном итоге попасть на корневую страницу. Поскольку разработчик не планировал разрешать пользователям доступ к корневой странице, соответствующая страница не была предоставлена, и мы получим 404 (или, в зависимости от конфигурации/типа переписывания, возможно, 500).
Если сайт использует кэширование/CDN систему, это может принудительно кэшировать 404 ответ, что приведет к недоступности страницы и серьезно повлияет на доступность сайта.
разъяснение
С момента публикации уведомления о безопасности мы получили несколько запросов от людей, которые беспокоятся о безопасности своих приложений и не совсем понимают масштаб атаки. Необходимо уточнить, что уязвимым элементом является промежуточное ПО. Если вы не используете промежуточное ПО (или, по крайней мере, не используете его для чувствительных целей), то не о чем беспокоиться (хотя проверьте упомянутые выше аспекты DoS), потому что обход промежуточного ПО не обходит никакие реальные механизмы безопасности.
В противном случае последствия могут быть катастрофическими, мы рекомендуем вам быстро внедрить меры, указанные в уведомлении о безопасности.
Безопасностное уведомление - CVE-2025-29927
патч
Для Next.js 15.x эта проблема была исправлена в версии 15.2.3
Для Next.js 14.x эта проблема была исправлена в версии 14.2.25
Для версий Next.js от 11.1.4 до 13.5.6 мы рекомендуем ознакомиться со следующими решениями.
Решение
Если вы не можете обновиться до безопасной версии, мы рекомендуем вам заблокировать доступ внешних пользовательских запросов с заголовком запроса x-middleware-subrequest к вашему приложению Next.js.
Серьезность
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N(Серьезность: 9.1/10, критический уровень)
больше информации
На момент написания этой статьи приложения, развернутые на Vercel и Netlify, очевидно, больше не подвержены этой уязвимости (обновление: из-за большого количества ложных срабатываний Cloudflare изменил это правило так, чтобы оно действовало только при активном включении пользователем — эти ложные срабатывания не смогли эффективно различить запросы от законных пользователей и потенциальных злоумышленников).
Отказ от ответственности
Данное исследование публикуется исключительно в образовательных целях и предназначено для помощи разработчикам в понимании коренных причин проблемы или для предоставления вдохновения исследователям / охотникам за уязвимостями в их будущей исследовательской деятельности. Эта статья является дополнительным материалом к уведомлению о безопасности, в которой содержится дальнейшее объяснение и уточнение природы уязвимости — поскольку в уведомлении уже были опубликованы заголовки запросов, которые привели к данной уязвимости (а также соответствующие различия в отправках).
Мы явно заявляем, что не поддерживаем какое-либо неэтичное использование данного текста.
Заключение
Как подчеркивается в этой статье, этот уязвимость существует в исходном коде Next.js уже несколько лет и изменяется вместе с эволюцией промежуточного программного обеспечения и его версий. Любое программное обеспечение может иметь серьезные уязвимости, но когда это затрагивает один из самых популярных фреймворков, это становится особенно опасным и может иметь серьезные последствия для более широкой экосистемы. Как уже упоминалось, на момент написания этой статьи Next.js загружается почти 10 миллионов раз в неделю. Он широко используется в таких критически важных областях, как банковские услуги и блокчейн. Когда уязвимость затрагивает зрелые функции, на которые полагаются пользователи (такие как авторизация и аутентификация), риск увеличивается.
Команда Vercel потратила несколько дней на исправление этой уязвимости, но стоит отметить, что, как только они осознали проблему, исправление было подано и объединено в новую версию всего за несколько часов (включая обратную портировку).
Временная линия :
27 февраля 2025 года: сообщено о уязвимости разработчикам (на тот момент мы полагали, что только версии с 12.0.0 по 12.0.7 затронуты, и указали это в отчете).
1 марта 2025 года: отправлено второе письмо, в котором говорится, что на самом деле все версии имеют уязвимости, включая последнюю стабильную версию.
5 марта 2025 года: получен предварительный ответ от команды Vercel, в котором сообщается, что версия 12.x больше не поддерживается (возможно, они еще не прочитали приложенный к нашему второму письму шаблон объявления о безопасности и не обратили внимания на то, что все версии подвержены риску).
5 марта 2025 года: повторно отправляю письмо, пожалуйста, команда, как можно скорее ознакомьтесь со вторым письмом и шаблоном уведомления о безопасности.
11 марта 2025 года: повторно отправить письмо, подтвердить, была ли принята новая информация.
17 марта 2025 года: получен ответ от команды Vercel, подтверждающий, что соответствующая информация принята к сведению.
18 марта 2025 года: получено письмо от команды Vercel, в котором сообщается, что отчет принят, патч исправления завершен. Через несколько часов вышла версия 15.2.3 с исправлениями (включая исправления обратной совместимости).
21 марта 2025 года: Официальное объявление о безопасности.
В общем, процесс поиска нулевых уязвимостей становится захватывающим и адреналиновым только в тот момент, когда обнаруживается зацепка; остальное время — это путешествие, полное неопределенности — для любопытствующих оно приносит знания; для тех, кто не терпит ждать, это путешествие кажется особенно долгим. Не сомневайтесь, действовать в команде гораздо легче, чем пересекать пустыню в одиночку.