
Образовательная демонстрация уязвимости подделки серверных запросов (SSRF) в Next.js (CVE-2024-34351), с пошаговыми примерами эксплуатации и смягчения.
Этот репозиторий может служить материалом для одного или нескольких митапов. Маршрут следующий...
Эта работа основана в основном на двух источниках:
1-csr-load-data[!IMPORTANT] CSR (Client-Side Rendering): код React доставляется в браузер, который генерирует контент, вставляемый в DOM.

cd 1-csr-load-data
npm start

2-csr-router — маршрутизация в vanilla React SPA[!IMPORTANT] После первой загрузки страницы навигация по другим страницам того же сайта использует JavaScript для повторного рендеринга частей страницы без полной перезагрузки.
cd 2-csr-router
npm start

3-rsc-load-data — загрузка данных в React Server Components (реализация Next.js)[!IMPORTANT] Компоненты React, предназначенные для выполнения только на сервере, а не в браузере.

cd 3-rsc-load-data
npm run build
npm run start

4-rsc-router — маршрутизация в React Server Components (реализация Next.js)[!IMPORTANT] Компоненты выполняются только на сервере. Поведение по умолчанию — статический рендеринг: компоненты выполняются на этапе сборки.
cd 4-rsc-router
npm run build
npm run start

5-SSR — SSR (Server Side Rendering)[!IMPORTANT] SSR означает предварительный рендеринг клиентских компонентов на сервере. Код React выполняется в момент запроса. Результат может кешироваться для последующих запросов.
Рекомендация: определять компоненты с 'use client'; как можно ниже в дереве компонентов.
[!IMPORTANT] «В React „гидратация“ — это то, как React „прикрепляется“ к существующему HTML, который уже был отрисован React в серверной среде. Во время гидратации React пытается прикрепить обработчики событий к существующей разметке и взять на себя рендеринг приложения на клиенте. В приложениях, полностью построенных на React, обычно гидратируется только один „корень“, один раз при запуске всего приложения.»
cd 5-ssr
npm run build
npm run start

6-pages-router-ssg (реализация Next.js)[!IMPORTANT] SSG (Static Site Generation) с использованием pages router: код React выполняется при сборке приложения, а сгенерированный вывод статичен.
cd 6-pages-router-ssg
npm run build
npm run start
7-pages-router-isr (реализация Next.js)[!IMPORTANT] ISR (с использованием pages router): «Next.js позволяет создавать или обновлять статические страницы после сборки сайта. Инкрементальная статическая регенерация (ISR) позволяет использовать статическую генерацию для каждой страницы без необходимости пересобирать весь сайт. С ISR можно сохранить преимущества статики, масштабируясь до миллионов страниц.»
cd 7-pages-router-isr
npm run build
npm run start
«данные могут устареть во время запроса»
...
8-ssrf-14.1.014.1.1redirect(\/blog/${inputValue}`);`Next.JS выполняет запрос на стороне сервера, а затем возвращает результат браузеру:
redirect('/blog/123'); конструирует URL http://207.154.209.99/blog/123.
Для этого Next.JS получает хост 207.154.209.99 из HTTP-заголовка исходного запроса.Content-Type: text/x-component, Next.JS запрашивает URL с помощью HTTP GET.Для осуществления SSRF на целевом сервере необходимо запустить другой сервер:
Content-Type: text/x-component для любого HEAD-запроса
8-ssrf-14.1.0В /etc/nginx/sites-available/nextjs
До:
server {
listen 80 default_server;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
После:
server {
listen 80;
server_name 207.154.209.99;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host 207.154.209.99;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Риск побочных эффектов...

Страницы в каталоге app по умолчанию являются серверными компонентами. Это отличается от каталога pages, где страницы — клиентские компоненты.
Обновление до Next.js 13 не требует использования нового App Router. Вы можете продолжать использовать pages с новыми функциями, которые работают в обоих каталогах.
Если требуется сравнить производительность загрузки для различных решений, можно добавить метрики Web Core Vitals в console.log.
ISR с использованием App Router?
В App Router Next.js все полученные данные по умолчанию являются статическими и отрисовываются во время сборки. Однако это легко изменить: Next.js расширяет объект параметров fetch, предоставляя гибкость в правилах кеширования и ревалидации. Вы можете использовать опцию
{next: {revalidate: number}}для обновления статических данных через заданные интервалы или при изменениях на бэкенде (инкрементальная статическая регенерация), а опцию{cache: 'no-store'}можно передать в fetch-запросе для динамических данных (рендеринг на стороне сервера).