Server-Side Request Forgery (SSRF) не случайно получила отдельное место A10:2021 в OWASP Top 10: это одна из немногих уязвимостей, позволяющая внешнему атакующему выполнять запросы изнутри вашей инфраструктуры, используя доверие, которым уже наделены ваши серверы. Единственный непроверенный параметр URL может стать мостом из публичного интернета прямо к внутренним сервисам, приватным API и — что опаснее всего — к эндпоинту метаданных облака, выдающему временные учётные данные.
Что такое SSRF на самом деле
SSRF возникает всякий раз, когда приложение загружает удалённый ресурс по URL (либо по хосту или IP), на который может влиять пользователь, без проверки того, куда такому запросу вообще разрешено идти. Классические точки — прокси изображений, валидаторы вебхуков, генераторы превью ссылок, рендереры PDF, импортёры документов и любая функция «импорт по URL». Сервер приложения послушно выполняет запрос от имени атакующего, а поскольку он находится за файрволом, дотягивается туда, куда сам атакующий напрямую никогда бы не попал.
Каноническое соответствие — CWE-918: Server-Side Request Forgery. Неаутентифицированный, удалённо эксплуатируемый SSRF, читающий облачные учётные данные, обычно получает оценку в диапазоне CVSS 9.1–9.9 — например AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N, где флаг Scope: Changed отражает прыжок из веб-уровня в плоскость облачной идентичности.
Цепочка атаки по шагам
Рассмотрим эндпоинт, генерирующий превью ссылок:
- 1. Обнаружение. Атакующий находит
POST /api/preview {"url":"https://example.com/article"}и замечает, что ответ встраивает загруженное содержимое. Он подставляетhttp://127.0.0.1:8080/и получает внутреннюю админ-страницу — SSRF подтверждён. - 2. Внутренняя разведка. Он прощупывает
http://169.254.169.254/, диапазоны10.0.0.0/8и типичные порты (Redis 6379, Elasticsearch 9200, Consul 8500), чтобы понять, до чего сервер способен дотянуться. - 3. Удар по сервису метаданных. В AWS со старым IMDSv1 обычный GET на
http://169.254.169.254/latest/meta-data/iam/security-credentials/возвращает имя привязанной роли IAM, а его дописывание — JSON сAccessKeyId,SecretAccessKeyиToken. - 4. Кража учётных данных и боковое перемещение. Атакующий экспортирует временные ключи, выполняет
aws sts get-caller-identityи действует уже как роль инстанса EC2 — читает бакеты S3, таблицы DynamoDB, а при избыточных правах эскалирует по всему аккаунту.
Взлом Capital One в 2019 году — более 100 миллионов записей — прошёл ровно по этой схеме: SSRF против неверно настроенного компонента достиг эндпоинта метаданных, забрал учётные данные роли и позволил выгрузить данные из S3.
Почему 169.254.169.254 так опасен
Блок 169.254.0.0/16 — это диапазон IPv4 link-local (RFC 3927). Каждое крупное облако привязывает свой Instance Metadata Service (IMDS) к 169.254.169.254 — AWS, Google Cloud (через metadata.google.internal) и Azure. По замыслу он неаутентифицирован: любой процесс на хосте, включая ваше приложение, делающее исходящий запрос, может его прочитать. Это не проблема, пока цель запроса выбирает не атакующий.
Обходы, которые упускают защитники
Наивные блок-листы, сверяющие лишь строку «169.254.169.254» или «localhost», не устоят против:
- Альтернативных кодировок IP:
http://2852039166/(десятичное),http://0xA9FEA9FE/(шестнадцатеричное) илиhttp://[::ffff:169.254.169.254]/(IPv6-mapped). - DNS rebinding: имя хоста, которое при валидации разрешается в безопасный IP, а при самой загрузке — в
169.254.169.254(TOCTOU между проверкой и использованием). - Редиректов: указанный URL возвращает
302на внутренний адрес, за которым следует HTTP-клиент. - Альтернативных схем:
file://,gopher://илиdict://, чтобы достать внутренние сервисы вне HTTP.
Защита, которая действительно работает
Применяйте эти слои вместе — ни один отдельный контроль недостаточен:
- Включите IMDSv2 и hop-limit 1. IMDSv2 требует токен сессии, получаемый запросом
PUTс заголовкомX-aws-ec2-metadata-token-ttl-seconds; SSRF через обычный GET (самый частый случай) такой токен создать не может. Установите инстансуHttpTokens=requiredиHttpPutResponseHopLimit=1, чтобы контейнеры не дотягивались до метаданных. Это одно исправление с наивысшей ценностью. - Allow-лист, а не блок-лист. Проверяйте цель по явному allow-листу схем (только
https), хостов и портов. Всё остальное отклоняйте по умолчанию. - Разрешите, затем зафиксируйте. Разрешите имя хоста в IP, убедитесь, что он публичный (отклоните приватные RFC 1918, loopback, link-local 169.254.0.0/16 и эквиваленты IPv6), затем подключайтесь к именно этому IP — закрывая окно DNS rebinding. Повторяйте валидацию после каждого редиректа и отключайте автоматическое следование, где возможно.
- Контроль исходящего трафика. Разместите загружающую нагрузку в подсети с группой безопасности / файрволом, запрещающим исходящий трафик к IP метаданных и внутренним диапазонам. Глубокая защита на случай обхода валидации на уровне приложения.
- Минимальные привилегии IAM. Исходите из того, что учётные данные утекут; ограничьте роль инстанса минимумом и используйте короткие TTL, чтобы украденные токены быстро истекали.
SSRF дёшев в эксплуатации и катастрофичен, когда попадает в сервис метаданных. Считайте любой контролируемый пользователем URL враждебным, валидируйте на уровне разрешённого IP и включите IMDSv2 уже сегодня — это бесплатное изменение конфигурации, нейтрализующее самый частый путь атаки.