flawopen.com/SSRF/SSRF в Node.js fetch()
Защищает ли Node.js fetch() от SSRF?
Нет. Серверный fetch() отправляет запрос от имени сервера. Если вызывающий выбирает адрес, он может направить сервер к системам, недоступным напрямую. Это как попросить курьера доставить посылку без проверки адреса. Риск зависит от сети, учётных данных, правил URL и перенаправлений.
providerId с источником, настроенным приложением. Не принимает произвольные URL.Причина: сервер доверяет выбранному пользователем адресу
Node.js fetch() — универсальный HTTP-клиент, а не политика защиты от SSRF. Он не ограничивает доступные сети; браузерный CORS не создаёт такую границу на сервере. Разобрать URL недостаточно: разрешённое имя может указывать на запрещённый адрес, а ответ перенаправить на другой хост. Функции загрузки аватаров, webhook, документов или предпросмотра по URL пользователя могут открыть этот путь.
Как запрос пересекает границу доверия
Пользователь влияет на URL
Эндпоинт принимает полный URL или данные для его построения, например для предпросмотра изображения.
Сервер отправляет запрос
HTTP-клиент использует сетевой маршрут, DNS, прокси и права процесса сервера.
Перенаправление меняет адрес
Fetch по умолчанию следует перенаправлениям. Сначала разрешённый адрес может вернуть Location на запрещённый хост.
Ответ открывает доступные данные
Если сеть и правила это допускают, становятся доступны внутренние сервисы или облачные метаданные. Это зависит от окружения.
Уязвимый и более безопасный код Node.js
// Не загружайте произвольный URL от вызывающего.
const response = await fetch(userProvidedUrl);
// Пользователь выбирает ключ, а не сетевой адрес.
const destinations = new Map([
["status", new URL("https://status.example/")],
["docs", new URL("https://docs.example/")],
]);
const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");
const response = await fetch(target, {
redirect: "error",
signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");
Если пользователи должны указывать URL
Предпочитайте идентификатор провайдера с фиксированным адресом. Если нужны произвольные публичные URL, разрешайте только необходимые схемы и порты; отклоняйте user-info, loopback, частные, link-local и другие запрещённые IPv4/IPv6-адреса. Проверяйте все DNS-адреса и подключайтесь именно к проверенному адресу без повторного непроверенного разрешения. Отключайте перенаправления или проверяйте каждый переход. Ограничивайте исходящий трафик, включая адреса метаданных 169.254.169.254 и включённый IPv6 endpoint. Ограничьте время, размер ответа и параллелизм; не передавайте внутренние учётные данные.
Список защиты от SSRF
- ✓Заменяйте произвольные URL фиксированным сопоставлением проверенного ключа провайдера с адресом приложения.
- ✓Разрешайте только
https:и ожидаемые порты; отклоняйте учётные данные в URL, неизвестные хосты, IP-литералы и запрещённые диапазоны. - ✓Отключайте переходы через
redirect: "error"; если они нужны, проверяйте каждый адрес до подключения. - ✓Проверяйте все ответы A/AAAA и привязывайте соединение к проверенному IP, сохраняя проверку имени. Учитывайте повторы и прокси.
- ✓Блокируйте loopback, частные, link-local сети и метаданные, включая IPv6, на firewall или proxy выхода. Проверок приложения недостаточно.
- ✓Ограничьте время, объём ответа и параллельные запросы; не пересылайте cookies, заголовки авторизации и облачные секреты.
- ✓В AWS требуйте IMDSv2 и ограничьте доступ к метаданным как дополнительную защиту; это не заменяет проверку URL и сетевые ограничения.
Частые вопросы
Нет. Перенаправления, варианты IPv4/IPv6, DNS rebinding, прокси и гонки между разрешением и подключением обходят простую проверку. Используйте список разрешённых целей. Для произвольных адресов проверяйте каждый IP и подключайтесь именно к нему; применяйте те же правила на сетевом выходе.
Нет. IMDSv2 требует токен и снижает часть рисков, но SSRF может достигать других внутренних служб или метаданных при иной конфигурации. Контроль адресов и исходящего трафика всё равно нужен.
Первичные источники
- OWASP — предотвращение SSRF
- Node.js — глобальный API fetch
- Стандарт WHATWG Fetch — режим перенаправлений
- AWS — настройки сервиса метаданных EC2
- CWE-918 — Server-Side Request Forgery