Статья Захват поддомена через Subdomain Takeover: от dangling DNS до полной эксплуатации

Распечатка DNS-зонного файла на тёмной бумаге, критическая строка обведена янтарным маркером. Рядом лежит перьевая ручка, на экране ноутбука светится вывод терминала.


На bug bounty программе в прошлом квартале я наткнулся на поддомен staging.target.example - его CNAME указывал на target-staging.azurewebsites.net, ресурс Azure, удалённый три месяца назад. От первого dig до подтверждённого захвата поддомена прошло двенадцать минут. Двенадцать. Такие dangling DNS записи - одна из самых недооценённых дыр на внешнем периметре: искать просто, эксплуатировать ещё проще, а организации узнают о проблеме только после инцидента. 95% русскоязычных материалов по теме рассказывают «как предотвратить». Здесь - наступательная сторона: как найти, верифицировать и захватить поддомен руками, с конкретными командами и разбором ложных срабатываний.
В статье использованы материалы из зарубежных источников.

Dangling DNS запись: механика уязвимости глазами атакующего​

Механика subdomain takeover строится на рассинхронизации между DNS-зоной и жизненным циклом внешнего ресурса. Организация создаёт CNAME-запись app.company.comcompany-app.azurewebsites.net, разворачивает приложение на Azure, а потом сносит облачный ресурс - но забывает убрать DNS-запись. CNAME указывает в никуда: это dangling CNAME запись, «висячая» запись DNS. По описанию Microsoft, сценарий типовой для организаций, которые регулярно создают и удаляют облачные ресурсы.

Атакующий находит такую запись, создаёт ресурс с тем же FQDN у облачного провайдера и получает полный контроль над содержимым поддомена жертвы. Согласно OWASP Web Security Testing Guide (WSTG-CONFIG-10), эксплуатация возможна для записей типов A, CNAME, MX, NS и TXT. Причём NS takeover даёт контроль над всей DNS-зоной домена - максимальный impact по классификации OWASP.

В терминологии MITRE ATT&CK subdomain takeover затрагивает несколько тактик. На этапе разведки - сбор DNS-данных о жертве (T1590.002) и пассивный DNS (T1596.001). Сам захват поддомена ближе всего к Resource Development - приобретение инфраструктуры через домен (T1583.001) или компрометация DNS-сервера (T1584.002). Дальнейшее использование захваченного поддомена покрывает Impact - External Defacement (T1491.002). Захваченный поддомен также покрывает Stage Capabilities: Link Target (T1608.005) при использовании для фишинга и Match Legitimate Resource Name (T1036.005) для обхода репутационных фильтров.

Что получает атакующий после успешного захвата поддомена:
  • Фишинговую страницу на легитимном домене организации
  • Перехват session cookies, если они установлены с атрибутом Domain=.company.com - без этого атрибута cookie привязаны к конкретному хосту и не отправляются на поддомены. Secure-флаг не спасёт, потому что атакующий выпустит валидный TLS-сертификат через Let's Encrypt на контролируемый поддомен
  • Площадку для эскалации: XSS, CSRF, обход CORS (по данным Microsoft, все эти атаки возможны через захваченный поддомен)
  • При NS takeover - полный контроль над DNS-зоной, включая MX-записи и перехват почты

Поиск уязвимых поддоменов: subdomain enumeration tools в действии​

Прежде чем искать dangling записи, нужно собрать максимально полный список поддоменов цели. Subdomain enumeration - первый этап, и чем шире покрытие, тем выше шанс найти забытый staging или dev-поддомен с висячей CNAME-записью.

Требования к окружению​

  • ОС: Linux (Kali 2024.x / Ubuntu 22.04+) или macOS; Windows - через WSL2
  • Go 1.21+ для subfinder, dnsx, subjack
  • Python 3.10+ для BadDNS, dnsrecon
  • Минимум 4 ГБ RAM, 2 ГБ свободного диска
  • Стабильный интернет - passive recon требует API-запросов к Shodan, SecurityTrails, VirusTotal
  • API-ключи: SecurityTrails, Shodan, VirusTotal, Censys - бесплатных тарифов хватит за глаза для большинства целей

Passive recon: CNAME-цепочки без единого запроса к цели​

На этапе пассивной разведки цель - собрать поддомены из открытых источников, не отправляя ни одного пакета к инфраструктуре цели. Для subdomain takeover bug bounty это критично: некоторые программы явно запрещают active enumeration до определённого этапа.

subfinder (ProjectDiscovery, Go, активно поддерживается - регулярные релизы в 2024) - агрегатор пассивных источников. Запуск: subfinder -d target.com -all -o subs.txt. Флаг -all подключает все сконфигурированные API-провайдеры. На выходе - плоский список поддоменов без резолвинга.

amass (OWASP, Go, активно поддерживается) - тяжёлая артиллерия с графовой моделью. В passive-режиме использует Certificate Transparency logs, DNS-агрегаторы и веб-архивы: amass enum -passive -d target.com -o amass_subs.txt.

Объединяем: cat subs.txt amass_subs.txt | sort -u > all_subs.txt. На крупных программах пересечение subfinder и amass - 60-70%. Оставшиеся 30-40% уникальных для каждого инструмента поддоменов и есть причина запускать оба. Я пробовал обходиться одним subfinder - стабильно терял находки, которые amass вытаскивал из CT-логов.

Резолвинг и извлечение CNAME через dnsx​

Следующий шаг - отрезолвить собранные поддомены и вытащить CNAME-записи. dnsx (ProjectDiscovery, Go, активно поддерживается) делает это массово:
Bash:
cat all_subs.txt | dnsx -cname -resp -o cname_records.txt
На выходе - строки вида sub.target.com [alias.provider.com]. Это сырьё для fingerprinting. Отдельно стоит прогнать список через dnsx -a -resp-only и сохранить IP-адреса - пригодится для проверки A-записей, указывающих на несуществующие ресурсы.

Ограничение: dnsx отправляет DNS-запросы к публичным резолверам. Если scope программы ограничивает active reconnaissance - этот шаг уже выходит за пассивный периметр. Уточняйте правила, прежде чем слать пакеты.

Альтернатива для этапа enumeration - dnsrecon (Python), который упоминается в OWASP WSTG как инструмент для DNS-перечисления. dnsrecon -d target.com выдаёт записи A, CNAME, NS, MX в одном прогоне. Для быстрой ручной проверки одного домена - хватает.

CNAME Takeover: fingerprinting и верификация уязвимости​

Не каждый CNAME, который не резолвится, означает захват поддомена. Разница между «поддомен не отвечает» и «поддомен реально уязвим к клейму» - именно то, что отделяет оплаченный баг-репорт от false positive, который убьёт вашу репутацию в программе.

Fingerprint-ответы облачных провайдеров​

Каждый облачный сервис при обращении к несуществующему ресурсу возвращает характерный ответ. По этим fingerprints инструменты определяют тип уязвимости:

ПровайдерТип ресурсаFingerprint-строкаСтатус
GitHub Pages*.github.io"There isn't a GitHub Pages site here"Требует верификации домена
Azure App Service*.azurewebsites.net"404 Web Site not found"Требует TXT-подтверждения
AWS S3*.s3.amazonaws.com"NoSuchBucket"Ограниченно уязвим: AWS внедрил cooldown periods и дополнительные защиты (2024-2025)
Heroku*.herokuapp.com"No such app"Edge case: требуется верификация custom domain через ACM
FastlyCNAME на Fastly"Fastly error: unknown domain"Уязвим
Shopify*.myshopify.com"Sorry, this shop is currently unavailable"Edge case

Верификация вручную - обязательный шаг перед отчётом. Алгоритм на пальцах:
  1. dig CNAME sub.target.com +short - убедиться, что CNAME действительно указывает на внешний сервис
  2. dig A <cname-target> +short - если NXDOMAIN, ресурс удалён
  3. curl -sI https://sub.target.com - искать fingerprint в теле или заголовках ответа
  4. Проверить доступность имени у провайдера (без фактического создания ресурса)
Согласно OWASP WSTG, DNS-ответы, требующие расследования: NXDOMAIN, SERVFAIL, REFUSED и ситуация «no servers could be reached».

Ложные срабатывания: как не испортить отчёт​

Типичные false positives, на которых горят начинающие охотники:

CNAME на внутренний балансировщик. Поддомен резолвится через CNAME на internal-lb.company.com, который возвращает NXDOMAIN из публичной сети, но прекрасно работает из корпоративной. Это split-horizon DNS - не уязвимость. Я сам в начале один раз чуть не отправил такой отчёт.

Провайдер с верификацией домена. Не все облачные платформы позволяют привязать произвольный домен без подтверждения владения. Если провайдер защищён - захват поддомена невозможен, даже если dangling CNAME запись существует. Статус верификации у конкретных провайдеров меняется - GitHub Pages, например, ужесточил проверки.

Wildcard DNS. Если *.target.com резолвится на один IP, каждый несуществующий поддомен будет отвечать - но это не dangling CNAME, а особенность конфигурации. Проверяется за секунду: dig A randomgarbage12345.target.com +short.

Перед отправкой отчёта проверяйте конкретный провайдер по репозиторию can-i-take-over-xyz на GitHub - сообщество поддерживает актуальный список сервисов с пометками «Vulnerable», «Not Vulnerable», «Edge Case». По данным Black Lantern Security, этот репозиторий стал основной площадкой для обсуждения техник takeover.

Subdomain Takeover автоматизация: nuclei, subjack, BadDNS​

Ручная проверка каждого поддомена не масштабируется. Для программ с тысячами поддоменов нужен pipeline автоматизации. Три инструмента, каждый со своим подходом.
🔓 Часть контента скрыта: Эксклюзивный контент для зарегистрированных пользователей.

DNS Misconfiguration за пределами CNAME: NS и MX takeover​

CNAME takeover - самый частый сценарий, но далеко не единственный вектор DNS misconfiguration эксплуатации. По оценке OWASP, NS subdomain takeover имеет наивысший impact среди всех типов, поскольку даёт полный контроль над DNS-зоной.

Типичная ситуация: организация делегировала подзону dev.company.com через NS-записи стороннему DNS-провайдеру, потом отказалась от его услуг, но не убрала делегацию. Атакующий создаёт зону у того же провайдера и контролирует все записи *.dev.company.com. Проверка: dig NS dev.company.com +short. Если NS-серверы не отвечают или домен NS-сервера доступен для регистрации - потенциальная уязвимость захвата поддомена. BadDNS автоматизирует эту проверку через модуль ns.

Ограничение NS takeover: по данным Black Lantern Security, эксплуатация через AWS Route53 стала сложнее - AWS внедрил защитные меры. Случаи успешного takeover подтверждены, но стабильность хуже, чем раньше.

Dangling MX-запись, указывающая на домен, доступный для регистрации, позволяет перехватывать почту организации. Impact зависит от приоритета записи: перехват записи с наивысшим приоритетом направляет всю почту на сервер атакующего. Представьте: вся корпоративная переписка льётся к вам - и вы даже ничего не ломали, просто зарегистрировали домен.

Модуль references в BadDNS заслуживает отдельного внимания - он ищет hijackable домены в JavaScript и CSS-ссылках на странице. Это second-order subdomain takeover: если домен, откуда подгружается JS, можно захватить - последствия эквивалентны stored XSS. Сканеры типа nuclei это не покрывают.

Контекст применения в пентесте и bug bounty​

Subdomain takeover как вектор при DNS hijacking пентесте имеет чёткие границы. Не стоит тащить эту технику в каждый проект.

Где техника работает: bug bounty программы с wildcard-доменами в scope; external pentest и EASM-аудит; red team engagement на этапе initial access - захваченный поддомен становится идеальной площадкой для фишинга или watering hole атаки.

Где не работает: internal pentest с split-horizon DNS; организации с зрелым управлением DNS через IaC (Terraform, Pulumi) и автоматической очисткой orphaned records; провайдеры с обязательной верификацией владения доменом - ограничивает возможности, хотя не исключает их полностью.

Оговорка по инфраструктуре: для modern-окружений с Infrastructure-as-Code dangling записей значительно меньше, чем для legacy-инфраструктур, где DNS управляется руками через веб-панель регистратора. Основная масса находок приходится на организации во второй категории - и таких, поверьте, хватает.

За последний год я проверил больше двух тысяч dangling CNAME-записей в рамках различных программ. Реально эксплуатабельных - менее 3%. Остальные - split-horizon DNS, провайдеры с верификацией, wildcard-резолвинг или просто битые записи без возможности клейма. Разница между пустым отчётом и оплаченным багом - в тридцати секундах ручной проверки через dig и curl, которые многие пропускают, гоняясь за автоматизацией.

Ещё один тренд, который стоит учитывать: крупные облачные провайдеры закручивают гайки. GitHub Pages требует верификацию, Azure App Service усложнил привязку custom domains, AWS Route53 добавил защиту от NS takeover. Через год-два классический CNAME takeover через крупных провайдеров станет экзотикой. Зато «длинный хвост» из мелких SaaS-платформ, конструкторов лендингов и региональных облаков растёт - и именно там сейчас самые реальные находки. По ним нет сигнатур ни в nuclei-templates, ни в dnsReaper - приходится создавать свои fingerprints и отправлять PR в can-i-take-over-xyz. Кто этим занимается, тот и снимает сливки. На HackerLab лежит сценарий, где этот primitive нужно собрать в полную цепочку.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab