ダングリング CNAME とサブドメインテイクオーバーを実例ベースで解説
この記事の対象読者
- Web セキュリティに興味があるエンジニア
- Bug Bounty を始めたい / 始めたばかりの人
- インフラ・DNS まわりを触っている人
はじめに
会社でマーケティング用の LP、ヘルプデスク、メール配信とか、外部 SaaS を使っていませんか?
導入するとき、こんな作業をしたはずです。
「DNS に CNAME レコードを追加してください」
で、SaaS を解約したとき、その CNAME レコード…… 消しましたか?
消し忘れていると、それは ダングリング CNAME と呼ばれる状態になります。最悪、攻撃者にサブドメインを乗っ取られます。これが サブドメインテイクオーバー です。
この記事では、以下をまとめました:
- ダングリング CNAME がなぜ起きるのか
- それがどうサブドメインテイクオーバーに繋がるのか
- 実際にどうやって見つけるのか
- Bug Bounty で報告するときの注意点(事実と仮定の分離が大事)
- 防御側の対策
実際に Bug Bounty でこの種の問題を見つけて報告した経験をもとに書いています。
ダングリング CNAME とは
通常の CNAME の動き
外部 SaaS でカスタムドメインを使うとき、自社のサブドメインから SaaS 側のホスト名へ CNAME レコードを設定しますよね。
blog.example.com → CNAME → example.someservice.com → A → 203.0.113.10
- ユーザーが
blog.example.comにアクセス - DNS が CNAME を辿り、
example.someservice.comの A レコードで IP アドレスを取得 - その IP のサーバー(SaaS)がコンテンツを返す
図にするとこうです:
ユーザー
│
│ "blog.example.com にアクセスしたい"
▼
DNS サーバー
│
│ "blog.example.com は example.someservice.com の別名だよ"
│ "example.someservice.com の IP は 203.0.113.10 だよ"
▼
SaaS のサーバー (203.0.113.10)
│
│ "blog.example.com 用のコンテンツを返すよ"
▼
ユーザーにコンテンツが表示される
ダングリングが起きるとき
で、SaaS の利用をやめたとします。SaaS 側のアカウントやリソースは消えた。でも自社 DNS の CNAME レコードは?
blog.example.com → CNAME → example.someservice.com → A → ??? (解決不能)
SaaS は消えたのに、DNS の矢印だけが虚空を指してる。 これが ダングリング CNAME(dangling = 宙ぶらりん)です。
ユーザー
│
│ "blog.example.com にアクセスしたい"
▼
DNS サーバー
│
│ "blog.example.com は example.someservice.com の別名だよ"
│ "...でも example.someservice.com の IP がないぞ?"
▼
エラー: ホストを解決できません
この状態自体は「ページが表示されない」だけなので、一見無害に見えます。が……
なぜ危険なのか — サブドメインテイクオーバー
ダングリング CNAME がやばいのは、攻撃者がその SaaS で同じドメインを再登録できる場合がある からです。
攻撃の流れ
1. 攻撃者が blog.example.com のダングリング CNAME を発見
↓
2. CNAME 先の SaaS に自分のアカウントを作成
↓
3. SaaS 上で blog.example.com をカスタムドメインとして登録
↓
4. SaaS が blog.example.com に対してコンテンツを返すようになる
↓
5. blog.example.com にアクセスすると攻撃者のコンテンツが表示される
DNS レコードの持ち主(example.com の管理者)は何も変えていません。なのに blog.example.com が乗っ取られました。
ユーザー
│
│ "blog.example.com にアクセスしたい"
▼
DNS サーバー
│
│ "blog.example.com は example.someservice.com の別名だよ"
│ "example.someservice.com の IP は 198.51.100.1 だよ" ← 攻撃者が SaaS に登録した結果
▼
攻撃者のコンテンツ (198.51.100.1)
│
│ "偽のログインページを返すよ"
▼
ユーザーが騙される
成立した場合の影響
| 影響 | 説明 |
|---|---|
| フィッシング | 正規ドメイン上に偽ログインページを設置可能。URL が正規なのでユーザーが信頼しやすい |
| Cookie 送信 / セッション悪用の可能性 |
Domain=.example.com でスコープされた Cookie が攻撃者管理のサブドメインに送信される可能性がある。Cookie 属性やアプリ側の設計によっては、セッション悪用の踏み台になり得る |
| CSP バイパス | 親サイトの CSP が *.example.com のようにサブドメインを信頼している場合、乗っ取られたサブドメインを足がかりに想定外のスクリプト配信経路になることがある |
特に Cookie の問題は見落とされがち。多くの Web アプリは Cookie を .example.com みたいな広いスコープで設定しています。サブドメインが乗っ取られると Cookie がそこに送信される可能性があり、Cookie 属性(HttpOnly, SameSite 等)やアプリの設計次第ではセッション悪用に繋がり得ます。
発見方法
手順 1: サブドメインの列挙
まずは対象ドメインのサブドメインをパッシブに集めます。
# サブドメイン列挙ツール
subfinder -d example.com -silent
# 証明書透過性ログ (Certificate Transparency) から
curl -s "https://crt.sh/?q=%.example.com&output=json" | jq -r '.[].name_value' | sort -u
手順 2: CNAME レコードの確認
集めたサブドメインの CNAME を引きます。
dig blog.example.com CNAME +short
# → something.external-service.com.
外部サービスっぽいドメインを指してる CNAME が見つかったら、次へ。
手順 3: CNAME 先の解決可否を確認
dig something.external-service.com A +short
# → (応答なし) ← ダングリングの可能性あり!
A レコードが返らなければダングリングの可能性あり。ただし AAAA レコードや CNAME チェーンの先にリソースがある場合もあるので、追加確認はしておきましょう。
手順 4: HTTP アクセスの確認
curl -sv https://blog.example.com/
# パターン A: "Could not resolve host" → DNS 解決できず
# パターン B: SaaS の 404 / エラーページ → DNS は解決するが SaaS 側にリソースなし
パターン B も見逃せません。SaaS によっては DNS は解決するけど「このドメインは設定されていません」みたいなデフォルトページを返すケースがあって、これもテイクオーバーの候補になります。
まとめると
# ワンライナーで一括チェック(対象ドメインリストを入力)
cat subdomains.txt | while read sub; do
cname=$(dig "$sub" CNAME +short)
if [ -n "$cname" ]; then
a=$(dig "$cname" A +short)
if [ -z "$a" ]; then
echo "[DANGLING] $sub → $cname"
fi
fi
done
よくある CNAME 先のパターン
テイクオーバーできるかはサービスによって違うし、時期や仕様変更でも変わります。
| CNAME 先のドメイン | サービス | 一般的な傾向 |
|---|---|---|
*.amazonaws.com |
AWS S3 | 条件によって成立例あり |
*.azurewebsites.net |
Azure | 成立例あり |
*.herokuapp.com |
Heroku | 成立例あり |
*.github.io |
GitHub Pages | 成立例あり |
*.shopify.com |
Shopify | サービス側仕様による |
*.zendesk.com |
Zendesk | 成立例が知られている |
*.unbounce.com |
Unbounce | 成立例が知られている |
*.ghost.io |
Ghost | 条件次第 |
最新情報は EdOverflow/can-i-take-over-xyz や各サービスの公式ドキュメントで確認してください。
注意: このリポジトリに載っていないサービスもあります。載ってない = 安全、ではないです。
テイクオーバーが成立するかの判断
ダングリング CNAME を見つけただけでは、テイクオーバーが成立するとは限りません。成否は CNAME 先の SaaS の挙動 次第です。
成立する条件
- SaaS がカスタムドメインの再登録を許可する — 前のユーザーが解除した後、別アカウントから同じドメインを登録できる
- ドメイン所有権の検証がない、または CNAME のみ — TXT レコード等で所有権確認がある場合、攻撃者は DNS を操作できないので登録に失敗する
成立しないケース
- SaaS がドメイン所有権を TXT レコードで検証する
- SaaS が一度登録されたドメインを内部的にロック(保留)している
- SaaS がエンタープライズ専用で、アカウントを自由に作れない
- CNAME 先のドメイン自体が有効で、ワイルドカード応答している
実はこの「成立するか判断する」ところが一番難しいです。
Bug Bounty での報告
CWE は何を使う?
レポートに CWE を書く場合、だいたい以下のどれかになります:
- CWE-923 (Improper Restriction of Communication Channel to Intended Endpoints) — 「意図しないエンドポイントとの通信制限の不備」。ダングリング CNAME 自体を指すならこれが一番しっくりきます
- CWE-350 (Reliance on Reverse DNS Resolution for a Security-Critical Action) — DNS に依存したセキュリティ判断の問題。Cookie スコープや CSP の話と絡めるならこっち寄り
迷ったら CWE-923 を選んでおけば大丈夫です。HackerOne のサブドメインテイクオーバー系レポートでもよく使われています。
PoC ありの場合
テイクオーバーを実証できた場合(SaaS にドメインを登録して自分のコンテンツが表示されることを確認)、Medium〜High がつく可能性があります。ただ、実際に PoC を作るのは難しいケースが多いです(SaaS が有料のみ、エンタープライズ契約必要、そもそもしないでね。。。等)。
報告に含めるもの:
- ダングリング CNAME の DNS 証拠(
digの出力) - SaaS 上での再登録手順のスクリーンショット
- テイクオーバー後にブラウザで表示されるコンテンツの証拠
- 影響の説明(フィッシング、Cookie 窃取等)
PoC なしの場合
SaaS が検証できない(エンタープライズ専用でアカウント作成不可、等)場合でも、ダングリング CNAME の存在自体 を報告する価値はあります。
ただし、書き方がめちゃくちゃ重要 です。
大事な原則: 事実と仮定を分離する
- 「CNAME がダングリングしている」 → 事実(dig で確認済み)
- 「テイクオーバーが可能」 → 未検証の仮定
- 「Cookie が漏れる」 → 仮定の上の仮定(テイクオーバー可能 + Cookie スコープが広い)
ここの区別が曖昧だと、トリアージチームに "speculative"(推測的)と判断されて却下されやすくなります。
おすすめの報告構成
1. 観測事実(DNS 証拠のみ)
2. 未検証の点(テイクオーバー可否と、検証しなかった理由)
3. 潜在的影響(「テイクオーバーが成立した場合」と明示)
4. 推奨対応(CNAME の削除)
やりがちな NG 構成
1. 影響(フィッシング!Cookie 窃取!XSS!)
2. 再現手順(dig の出力)
3. ...あ、でもテイクオーバーは未検証です
これだと「結論ありきで書いて、後から言い訳してる」ように見えて、信頼性が下がります。
事実を先に、影響は後に。未検証の点は影響の前に。 これだけでレポートの通りやすさはかなり変わります。(ただ正直なところ、N/Aになりにくい、、、といった意味合いが大きいですが)
検証しなかった理由の書き方
「テストできなかった」ではなく「意図的にテストしなかった」と書くのがポイントです。
Bug Bounty では、スコープ外のサードパーティサービスに対してテストすること自体がルール違反になり得ます。「SaaS 側でドメイン登録を試みる」行為は、その SaaS に対するテストであり、対象プログラムのスコープ外です。
良い例: "The third-party service is outside the program scope, so these checks were intentionally not performed."
悪い例: "I couldn't verify because the service requires a paid account."
前者は判断に基づく行動、後者は能力不足に見えます。この違い、地味に大きいです。
現実的にどれくらいの評価がつくか
| 状態 | 期待される評価 |
|---|---|
| テイクオーバー実証済み(PoC あり) | Low〜Medium(Cookie 窃取等の連鎖があれば上がる可能性) |
| ダングリング CNAME のみ(PoC なし) | Informative〜Low |
| CNAME はあるが SaaS 側が安全と確認済み | N/A |
PoC なしだと報奨金は正直厳しいですが、企業が DNS をクリーンアップするきっかけにはなります。「出して損はない」くらいの温度感です。
防御側の対策
DNS ハイジーン(最重要)
- SaaS の利用停止時に CNAME レコードを消す — これに尽きます
- 定期的に DNS レコードを監査して、解決不能な CNAME を検出する
- IaC(Terraform, CloudFormation 等)で DNS を管理して、変更履歴を追えるようにする
自動検出の仕組み
# 簡易チェックスクリプトの例
# 自社が管理する全サブドメインのリストに対して定期実行
cat our-subdomains.txt | while read sub; do
cname=$(dig "$sub" CNAME +short 2>/dev/null)
if [ -n "$cname" ]; then
a=$(dig "$cname" A +short 2>/dev/null)
if [ -z "$a" ]; then
echo "[ALERT] Dangling CNAME: $sub → $cname"
fi
fi
done
これを cron や CI/CD に組み込んでおけば、ダングリング CNAME を早めに見つけられます。
Cookie のスコープを絞る
サブドメインテイクオーバーの影響を減らすために:
- Cookie を
Domain=.example.comみたいな広いスコープで設定しない -
Domain属性を省略すれば、Cookie は設定したホストにだけ送信される(サブドメインには送られない) - これはテイクオーバー対策に限らず、一般的なセキュリティのベストプラクティスです
まとめ
| ポイント | 内容 |
|---|---|
| 何が起きるか | 外部 SaaS の利用停止後に DNS の CNAME レコードを消し忘れる |
| なぜ危険か | 攻撃者が SaaS 上でドメインを再登録し、正規サブドメインを乗っ取れる可能性がある |
| 発見方法 |
dig コマンドで CNAME → A レコードの解決可否を確認するだけ |
| 報告のコツ | 事実と仮定を明確に分離し、未検証の点を正直に書く |
| 防御 | SaaS 解約時に CNAME を削除。定期的な DNS 監査で予防 |
ダングリング CNAME は、技術的に高度な攻撃ではありません。dig コマンドを打つだけで見つかることもあります。ただ、「見つけやすい」ことと「報告が通りやすい」ことは別の話。PoC の有無、事実と仮定の分離、報告の構成 — このあたりが Bug Bounty での評価を大きく左右します。
DNS レコードの管理は地味な作業ですが、消し忘れ一つでドメインの信頼性が揺らぐこともあります。定期的な監査、忘れずに。