Один и тот же адрес — четыре способа записи
SSRF-атаки: как злоумышленники используют DNS
Подделка запросов на стороне сервера (SSRF) возникает, когда злоумышленник заставляет сервер выполнить HTTP-запрос (или иной сетевой) от своего имени по адресу, выбранному не разработчиком приложения, а атакующим. Классический вектор: функция, которая загружает URL, переданный пользователем (импорт изображения, адрес вебхука, предпросмотр ссылки), а атакующий вместо публичного ресурса подставляет URL, указывающий на внутреннюю инфраструктуру.
Где в атаке участвует DNS
Наивная защита — проверять, похоже ли имя хоста в переданном URL на внутренний адрес. Это обходится тривиально: атакующий регистрирует публичный домен, направляет его DNS-запись на внутренний IP и передаёт вашему серверу совершенно обычное с виду имя хоста. Ваша проверка видит домен, а не IP: опасная часть проявляется только после DNS-разрешения, которое нередко происходит глубоко внутри библиотеки HTTP-клиента, выполняющей реальный запрос, уже после любой предварительной проверки.
Как выглядит настоящая защита
- Разрешайте имя хоста сами, явно, до выполнения любого запроса: не позволяйте HTTP-клиенту разрешать его невидимо от вашего имени.
- Проверяйте каждый полученный адрес (все, ведь домен может вернуть несколько) по чёрному списку приватных, loopback, link-local и облачных адресов метаданных.
- Отклоняйте запрос, если хотя бы один полученный адрес запрещён, а не проверяйте только первый из возвращённых.
- Проверяйте повторно в момент запроса, а не только при вводе, чтобы закрыть брешь DNS rebinding, описанную отдельно: на практике SSRF и rebinding часто сочетаются.
Здесь особого упоминания заслуживают облачные эндпоинты метаданных: у большинства облачных провайдеров запрос из виртуальной машины на определённый link-local-адрес может вернуть учётные данные, метаданные инстанса или конфигурацию, которые не предназначены для доступа снаружи машины. SSRF в сочетании с целью в виде эндпоинта метаданных — одна из самых распространённых и наиболее опасных цепочек эксплуатации в реальности, и начинается она всякий раз с обычного на вид доменного имени.
Фильтры, проверяющие строку, а не адрес, не работают
У IP-адреса больше допустимых текстовых представлений, чем учитывает большинство кода проверки. Фильтр, написанный как строковое сравнение с «127.0.0.1» или «localhost», пропускает любую из приведённых ниже альтернативных форм без изменений, потому что ни одна из них не похожа на искомую строку.
| Запись | Пример | Разрешается в |
|---|---|---|
| Стандартная десятичная с точками | 127.0.0.1 | 127.0.0.1 |
| Простое десятичное целое | 2130706433 | 127.0.0.1 |
| Восьмеричная | 0177.0.0.1 | 127.0.0.1 |
| Шестнадцатеричная | 0x7f.0.0.1 | 127.0.0.1 |
| Сокращённая форма (меньше 4 сегментов) | 127.1 | 127.0.0.1 |
Единственная надёжная защита — сначала разобрать адрес в его фактическое числовое значение и сверять с чёрным списком именно его. Именно такой подход использует собственный резолвер этого инструмента, а не сопоставление с шаблоном по тому, как адрес был записан. Резолвер возвращает нормализованный адрес независимо от того, как закодирована исходная запись имени хоста, поэтому разрешать имя сначала, а затем проверять результат надёжнее, чем пытаться проверять сырую строку во всех формах, которые атакующий может выбрать для записи.
Редиректы — другой частый обход
Даже система, которая корректно разрешает и проверяет исходный URL, может попасться на HTTP-редиректе. Запрос к одобренному публичному URL может получить ответ 302, указывающий на внутренний адрес, а HTTP-клиент, автоматически следующий за редиректами (поведение по умолчанию в большинстве библиотек), с готовностью выполнит этот второй запрос, ни разу не повторив проверку, которую первый запрос прошёл. Любая защита от SSRF, которая проверяет один раз, заранее, а затем позволяет HTTP-клиенту самому обрабатывать редиректы, имеет брешь точно такой же формы, какую создаёт DNS-разрешение, и устраняется она так же: проверять заново, явно, перед переходом по любому редиректу, а не полагаться на то, что URL, однажды прошедший проверку, и дальше будет указывать на безопасное место.
Нужно проверить публичные DNS-адреса домена? Воспользуйтесь инструментом Domain IP Lookup.
Читайте также
Один домен — два разных ответа
Первый запрос
разрешается в публичный IP
Проверка
пройдена — выглядит безопасно
Истекает TTL
через несколько секунд
Второй запрос
разрешается в 127.0.0.1
Что такое DNS rebinding и почему это важно
Домен, который сначала разрешается в безопасный адрес, а затем во внутренний: DNS rebinding превращает сам DNS в поверхность атаки.
Записи, которые встретятся почти в каждой зоне
Что такое CAA-запись: кто может выпускать сертификаты
Как записи DNS Certification Authority Authorization называют разрешённых эмитентов сертификатов и как избежать типичных ошибок конфигурации CAA.
Рекурсивный DNS-запрос: шаг за шагом
Браузер
нужен example.com
Резолвер
ваш провайдер / 1.1.1.1
Корень + TLD
кто отвечает за .com?
Авторитетный
настоящий ответ
Каждый шаг цепочки — тоже DNS-запрос, и его ответ потом кэшируется
DNSSEC: как проверяется подлинность DNS-ответов
Что делают подписи DNSSEC, записи DS и DNSKEY, как работает проверка и почему ошибки настройки приводят к ответам SERVFAIL.