Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Server-Side Request Forgery (SSRF)
SSRF (Server-Side Request Forgery) — это уязвимость веб-приложений, которая позволяет злоумышленнику манипулировать серверной частью приложения для выполнения произвольных HTTP запросов к внутренним или внешним ресурсам. Сервер выступает в роли «прокси» или «посредника», выполняя запросы, инициированные атакующим, но исходящие из доверенной среды сервера. Это позволяет обходить сетевые фильтры, firewalls и получать доступ к внутренним системам, которые обычно недоступны из внешней сети.
Механизм работы SSRF
Уязвимость возникает, когда приложение принимает URL или данные, указывающие на ресурс (например, для загрузки изображения, получения данных API, импорта файлов), и выполняет запрос на сервере без должной валидации и ограничений. Типичный сценарий:
- Приложение имеет функционал, который принимает URL от пользователя.
- Этот URL передается в серверную функцию (например, в PHP, Node.js, Python), которая выполняет HTTP запрос.
- Злоумышленник предоставляет URL, указывающий на внутренний сервис (например,
http://192.168.1.1/admin,http://localhost:8080,http://metadata.google.internal) или на внешний ресурс, который возвращает данные, полезные для атаки. - Сервер выполняет этот запрос и может вернуть ответ атакующему или выполнить действия на основе ответа.
Пример простого Node.js сервера с уязвимостью SSRF:
const express = require('express');
const axios = require('axios');
const app = express();
// Уязвимый endpoint, который принимает URL для загрузки данных
app.get('/fetch', async (req, res) => {
const url = req.query.url; // Пользователь контролирует этот параметр
try {
// Сервер выполняет запрос к указанному URL
const response = await axios.get(url);
res.send(response.data);
} catch (error) {
res.status(500).send('Error fetching data');
}
});
app.listen(3000);
Атакующий может вызвать этот endpoint с параметром:
/fetch?url=http://localhost:8080/internal-api
И сервер сделает запрос к внутреннему API на порту 8080, который может быть недоступен напрямую из интернета.
Типы SSRF и цели атаки
SSRF можно разделить на два основных типа:
- Basic SSRF: Сервер выполняет запрос и возвращает ответ напрямую клиенту. Атакующий видит результат запроса (например, содержимое внутренней страницы).
- Blind SSRF: Сервер выполняет запрос, но не возвращает ответ клиенту. Однако запрос может вызвать действия на внутреннем сервисе (например, запуск процедуры, изменение данных). Атакующий может определить успешность атаки по косвенным признакам (изменение поведения приложения, время ответа).
Основные цели атак с использованием SSRF:
- Доступ к внутренним сетям и сервисам: Обход firewall и получение данных от внутренних API, административных интерфейсов, баз данных, сервисов мониторинга (например,
http://169.254.169.254для AWS Metadata). - Обход контроля доступа: Сервер часто имеет более широкий доступ внутри сети. Запросы, исходящие от сервера, могут быть разрешены для ресурсов, запрещенных для внешних IP.
- Раскрытие информации: Получение данных от внутренних сервисов, которые могут содержать конфиденциальную информацию, ключи, токены.
- Атаки на другие системы (Chain Attacks): Использование сервера как ступени для атак на другие внешние системы, маскируя источник запроса.
- Протоколы, кроме HTTP: В некоторых случаях сервер может поддерживать запросы по другим протоколам (file://, gopher://, dict://), что позволяет читать локальные файлы или взаимодействовать с другими сервисами.
Методы защиты от SSRF
Для фронтенд-разработчиков важно понимать, что защита от SSRF — это совместная задача фронтенда и бэкенда. Фронтенд может внедрять предварительную валидацию, но окончательная защита реализуется на сервере.
На фронтенд-уровне:
- Валидация ввода на клиенте: Проверка URL, предоставляемых пользователем, на соответствие ожидаемым форматам (например, только HTTPS, определенные домены). Однако это лишь удобство для пользователя и не является защитой, так как атакующий может обойти клиентскую валидацию.
- Ограничение возможностей интерфейса: Если функционал требует загрузки по URL, предоставить пользователю выбор из предопределенного списка доверенных источников или использовать загрузку файлов вместо URL.
На бэкенд-уровне (ключевая защита):
- Валидация и фильтрация URL: Использование белых списков (
whitelist) разрешенных доменов, IP-адресов и протоколов. Черные списки (blacklist) менее надежны. - Проверка схемы URL: Блокировка протоколов, кроме HTTP/HTTPS (file://, gopher://, ftp://).
- Запрет внутренних IP и доменов: Фильтрация запросов к локальным адресам (localhost, 127.0.0.1), приватным IP-адресам (192.168.x.x, 10.x.x.x), адресам loopback и облачных метаданных.
- Использование DNS проверок: Проверка, что разрешенный DNS имя не соответствует внутреннему IP. Учитывать DNS rebinding атаки.
- Изоляция сетевых запросов: Серверная функция, выполняющая запросы, должна работать в ограниченной сетевой среде с минимальными правами.
- Отключение слежения за редиректами: Настройка HTTP клиента на сервере так, чтобы он не следил за редиректами, которые могут привести к внутренним ресурсам.
- Аутентификация запросов к внутренним сервисам: Если внутренние запросы необходимы, они должны использовать внутренние механизмы аутентификации, недоступные извне.
Пример безопасного кода на Node.js с валидацией:
const express = require('express');
const axios = require('axios');
const app = express();
const ALLOWED_DOMAINS = ['api.trusted-external.com', 'cdn.example.com'];
function isValidUrl(url) {
try {
const parsed = new URL(url);
// Проверка протокола
if (!['http:', 'https:'].includes(parsed.protocol)) return false;
// Проверка по белого списку доменов
if (!ALLOWED_DOMAINS.includes(parsed.hostname)) return false;
// Блокировка внутренних адресов
if (parsed.hostname === 'localhost' || parsed.hostname.startsWith('192.168.')) return false;
return true;
} catch {
return false;
}
}
app.get('/fetch', async (req, res) => {
const url = req.query.url;
if (!isValidUrl(url)) {
return res.status(400).send('Invalid URL');
}
try {
const response = await axios.get(url);
res.send(response.data);
} catch (error) {
res.status(500).send('Error fetching data');
}
});
Почему фронтенд-разработчик должен знать о SSRF?
- Понимание архитектуры: Знание SSRF помогает понять важность разделения доверенных и недоверенных зон в сетевой архитектуре приложения.
- Дизайн API и интерфейсов: Фронтенд-разработчик может предложить дизайн форм и интерфейсов, который минимизирует риск передачи произвольных URL (например, использовать загрузку файлов через
input[type="file"]вместо поля для URL). - Взаимодействие с бэкендом: Возможность корректно обсуждать требования безопасности с бэкенд-разработчиками и тестировщиками.
- Тестирование безопасности: В рамках фронтенд тестирования можно проверять, что клиентская валидация не создает ложного чувства безопасности, и что все данные ревалидируются на сервере.
SSRF остается одной из критических угроз для современных веб-приложений, особенно в облачных и микросервисных архитектурах. Полное предотвращение требует строгой валидации на серверной стороне, сетевого segmentation и принципа минимальных привилегий для серверных функций, выполняющих внешние запросы.