Захват поддомена (subdomain takeover): как происходит и защита
Захват поддомена начинается с DNS-записи, указывающей на удалённый ресурс. Как используют висячие записи CNAME, NS, A и MX, как их найти и предотвратить захват.
Опубликовано: · 6 мин чтения
Захват поддомена (subdomain takeover) происходит, когда DNS-запись в вашей зоне всё ещё указывает на внешний ресурс, который вы больше не контролируете, и кто-то другой этот ресурс занимает. Типичный случай: shop.example.com — CNAME на хостинговую платформу, магазин закрыли, запись осталась. Если платформа позволяет любому зарегистрировать освободившееся имя, не доказывая контроль над доменом, злоумышленник делает это и отдаёт свой контент на вашем поддомене, с действительным сертификатом. Защита скучна и действенна: знать, какие записи указывают за пределы вашей инфраструктуры, и удалять DNS-запись до того, как удалить то, на что она указывает. В этой статье — варианты атаки, последствия, поиск с помощью dig и curl и чек-лист профилактики.
Как происходит захват
Ничего не взламывается в привычном смысле. Ваш DNS от вашего имени говорит: «это имя обслуживается вон там», а «вон там» — это пространство имён, общее для всех клиентов провайдера. Последовательность такая:
- Вы создаёте ресурс у облачного или SaaS-провайдера (хранилище, приложение на платформе, сайт службы поддержки или посадочную страницу) и направляете на него поддомен записью CNAME.
- Позже ресурс удаляют: проект закончился, подписку отменили, учётную запись закрыли.
- CNAME остаётся в зоне. Владельца у него нет, напомнить о нём некому. Это висячая запись (dangling record).
- Провайдер снова делает старое имя ресурса доступным и не проверяет, кто контролирует указывающий на него домен.
- Злоумышленник регистрирует это имя. С этого момента ваш поддомен отдаёт его контент.
Возможен ли шаг 4, зависит от провайдера. Многие сейчас требуют TXT-запись подтверждения или резервируют освобождённые имена, но вы редко знаете политику каждого сервиса, когда-либо подключённого к вашему домену.
Варианты
| Висячая запись | Что нужно злоумышленнику | Что он получает |
|---|---|---|
| CNAME на удалённый облачный или SaaS-ресурс | Занять то же имя ресурса у провайдера | Веб-контент на поддомене |
| CNAME на хост, чей домен истёк | Зарегистрировать этот домен | Всё, что находится под целью этого CNAME |
| NS-делегирование подзоны DNS-провайдеру, у которого зона удалена, или на серверы имён под истёкшим доменом | Создать зону у этого провайдера или зарегистрировать домен сервера имён | Полный контроль над подзоной: любой тип записи, любое имя ниже. Худший случай |
| A-запись на освобождённый облачный IP-адрес | Получить тот же IP-адрес: дело везения и повторных попыток | Веб-контент; скорее случайная атака, чем целевая |
| MX-запись на отключённый почтовый сервис | Занять домен у этого почтового сервиса | Входящая почта поддомена |
Почему это серьёзнее подменённой страницы
Поддомен вашего домена наследует доверие, которого домен-двойник не получит никогда:
- Фишинг под вашим настоящим именем.
login-help.example.comпроходит любой тренинг «посмотрите на адресную строку». - Cookie. Cookie, выставленные с
Domain=example.com, браузер отправляет на каждый поддомен, включая тот, которым теперь управляет злоумышленник. В зависимости от флагов это могут быть и сессионные cookie. - Списки разрешений, доверяющие
*.example.com. Настройки CORS, источники Content Security Policy, URI перенаправления OAuth и настройки единого входа часто доверяют всему домену. Захваченный поддомен оказывается внутри этого доверия. - Публично доверенные сертификаты. Тот, кто контролирует содержимое имени хоста, может пройти проверку домена по HTTP и получить для него действительный сертификат.
- Почта. При висячей MX-записи почта на адреса поддомена доставляется злоумышленнику, включая письма для сброса паролей от учётных записей, заведённых на такие адреса.
Как найти висячие записи
Начинайте со своей зоны, а не снаружи (типы записей описаны в статье типы DNS-записей). Экспортируйте каждую свою зону и выпишите записи, цель которых — не ваша инфраструктура: CNAME на чужие домены, NS-делегирования, MX-записи, а также A/AAAA-записи с адресами из диапазонов облачных провайдеров.
Затем проверьте каждую.
CNAME. Разрешите цель. Несуществующая цель — самый явный признак:
$ dig +short CNAME shop.example.com
promo-example.cloudhost.example.
$ dig promo-example.cloudhost.example
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4711
NXDOMAIN для цели означает, что запись указывает в пустоту. Если цель разрешается (многие платформы отвечают на любое имя через wildcard), посмотрите на HTTP-ответ:
$ curl -sI https://shop.example.com | head -n 1
HTTP/2 404
Типовая страница провайдера «такого сайта нет», «такого хранилища нет» или «здесь пока ничего нет» на вашем поддомене означает, что ресурс за ним исчез. Проверьте также, что домен каждой цели CNAME по-прежнему зарегистрирован и принадлежит ожидаемому провайдеру.
NS-делегирования. Спросите каждый делегированный сервер имён напрямую, без рекурсии, является ли он авторитетным для подзоны:
$ dig +short NS sub.example.com
ns1.dns-host.example.
ns2.dns-host.example.
$ dig @ns1.dns-host.example sub.example.com SOA +norec
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 1289
REFUSED, SERVFAIL или ответ без флага aa означает, что этот сервер вашу зону не хранит. Полное отсутствие ответа может быть сетевой проблемой: повторите проверку, прежде чем делать выводы.
Имена, о которых вы забыли. Экспорт зоны находит записи; он не находит зоны, о существовании которых вы забыли, и имена, созданные другой командой у другого DNS-провайдера. Здесь помогают журналы Certificate Transparency: каждый публично доверенный сертификат в них регистрируется, поэтому они выдают имена хостов, для которых когда-то выпускали сертификат. Они же показывают сертификаты, которых вы не запрашивали, а это след, который оставляет захват.
Профилактика
Порядок действий. Одно это правило предотвращает большинство случаев:
- Вывод из эксплуатации: сначала удалите DNS-запись, дождитесь истечения TTL, потом удаляйте ресурс.
- Ввод в эксплуатацию: сначала создайте и проверьте ресурс, DNS-запись добавляйте последней.
Дайте записям владельцев. Вносите изменения в DNS через ревью, в идеале как инфраструктуру-как-код в том же репозитории, что и ресурс, на который они указывают, чтобы удаление ресурса и удаление записи были одним изменением.
Выбирайте провайдеров, которые проверяют домены. Провайдер, требующий TXT-запись подтверждения домена, прежде чем обслуживать пользовательский домен, не может быть использован посторонним для этой атаки.
Избегайте wildcard-CNAME на сторонние сервисы. *.example.com CNAME something.provider.example делает кандидатом любое возможное имя.
Ограничьте возможности поддомена. Для сессий используйте cookie только для хоста (без атрибута Domain). В списках разрешений CORS, CSP и URI перенаправления OAuth перечисляйте точные источники вместо *.example.com.
Понимайте, что CAA делает, а чего нет. CAA-запись ограничивает, какие удостоверяющие центры могут выпускать сертификаты для ваших имён. Захват она не останавливает: злоумышленник просто воспользуется разрешённым вами центром. Полезное дополнение — мониторинг Certificate Transparency на предмет сертификатов, которых никто с вашей стороны не запрашивал. Подробности в статье CAA-записи: что это и как настроить.
Чек-лист
- Все зоны у всех DNS-провайдеров известны и экспортированы.
- У каждой записи CNAME, NS, MX и A/AAAA с облачным IP есть названный владелец и назначение.
- Каждая внешняя цель CNAME разрешается, и её домен зарегистрирован на ожидаемого провайдера.
- На каждую делегированную подзону все её серверы имён отвечают авторитетно.
- Процедура вывода из эксплуатации гласит: сначала DNS-запись, потом ресурс.
- Ни один wildcard-CNAME не указывает на сторонний сервис.
- Сессионные cookie только для хоста; списки разрешений называют точные хосты.
- Журналы CT просматриваются на предмет неизвестных имён хостов и неожиданных сертификатов.
Если вы нашли висячую запись
- Немедленно удалите её (или, если сервис ещё нужен, сначала заново создайте ресурс в собственной учётной записи). Удаление записи прекращает уязвимость, как только истекут кэши.
- Выясните, был ли ресурс уже занят. Что поддомен отдаёт прямо сейчас?
- Если был: считайте cookie, привязанные к родительскому домену, скомпрометированными и аннулируйте сессии. Проверьте списки разрешений, включавшие поддомен.
- Просмотрите журналы CT на предмет сертификатов, выпущенных для этого имени за время уязвимости, и попросите выпустивший удостоверяющий центр отозвать те, которых вы не запрашивали.
- Исправьте процесс, из-за которого запись осталась, затем проверьте остальную зону: висячие записи редко приходят по одной.
Этика и закон
Проверяйте только домены, за которые отвечаете или которые вам письменно разрешено оценивать. Запрашивать публичный DNS безобидно. Занять ресурс за чужой висячей записью — совсем другое действие: вы будете отдавать контент под чужим именем и, возможно, получать cookie или почту чужих пользователей. Это несанкционированный доступ, даже с безобидной страницей-«доказательством» и благими намерениями. Если вы заметили висячую запись на не своём домене, сообщите владельцу через контакт из его файла security.txt (проверка security.txt покажет, опубликован ли он) и на этом остановитесь.
Частые ошибки
- Сначала удалить облачный ресурс, а «DNS почистить потом».
- Проверять только основную зону и забывать о делегированных подзонах.
- Доверять
*.example.comв настройках CORS, CSP или OAuth. - Верить, что CAA-запись предотвращает захват.
Проверьте в OrbitProbe
Поиск поддоменов в OrbitProbe перечисляет имена хостов под доменом, которые встречаются в публичных журналах Certificate Transparency, с датой последнего сертификата для каждого. Это реестр сертификатов, а не DNS: перечисленное имя может уже не существовать, а имя, которое пользовалось только wildcard-сертификатом, в списке будет отсутствовать, так что он дополняет экспорт зоны, а не заменяет его. Используйте его на доменах, за которые отвечаете, чтобы найти забытые хосты и сертификаты, которых никто не помнит заказывавшим, а затем проверьте каждое незнакомое имя DNS-запросом, чтобы увидеть, куда оно указывает сегодня.