5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【緊急】ワイルドカード証明書の誤用がサブドメイン乗っ取りを引き起こす仕組みと対策

5
Posted at

サブドメイン乗っ取り(Subdomain Takeover)は、削除されたサービスのCNAMEが残ったまま第三者にそのCNAME先のドメインを取得され、正規のHTTPS証明書まで発行できてしまう攻撃である。ワイルドカード証明書の誤用と組み合わさると、被害者サイトの任意のサブドメインで攻撃者がHTTPSページを提供できてしまう。本記事ではこの仕組みと検知・防止方法を解説する。

dangling DNS (ゾンビCNAME)とは

blog.example.com  CNAME  example-blog.github.io   ← 削除したのにCNAMEが残っている

example-blog.github.io のGitHub Pagesが削除されると、誰でも example-blog というリポジトリ名でGitHub Pagesを有効にすることができる。こうなると blog.example.com は攻撃者のコンテンツを指すことになる。

ワイルドカード証明書との組み合わせ

*.example.com のワイルドカード証明書が存在していると、サブドメイン乗っ取りが成功した後、攻撃者は blog.example.com でHTTPS(有効な証明書付き)のフィッシングページを提供できる。ブラウザは錠前マークを表示する。

影響を受けやすいサービスパターン

# GitHub Pages
subdomain.example.com  CNAME  user.github.io

# Heroku
api.example.com        CNAME  myapp.herokuapp.com

# AWS S3 (バケット削除後)
cdn.example.com        CNAME  mybucket.s3.amazonaws.com

# Azure
app.example.com        CNAME  myapp.azurewebsites.net

# Netlify
docs.example.com       CNAME  mysite.netlify.app

これらのサービスを解約・削除した際にCNAMEレコードを削除し忘れると危険な状態になる。

検知ツール: subjackとnuclei

# subjackのインストールと実行
go install github.com/haccer/subjack@latest

# サブドメインリストを用意して一括チェック
subjack -w subdomains.txt -t 100 -timeout 30 -o result.txt -ssl

# nucleiによる検知(テンプレート利用)
nuclei -l subdomains.txt -t ~/nuclei-templates/http/takeovers/
# サブドメインリストをDNSで総当たりし、CNAMEだけ抽出するPythonスクリプト
import dns.resolver
import sys

def check_cname(domain: str) -> str | None:
    try:
        answers = dns.resolver.resolve(domain, 'CNAME')
        return str(answers[0].target)
    except Exception:
        return None

subdomains_file = sys.argv[1]
with open(subdomains_file) as f:
    for line in f:
        sub = line.strip()
        cname = check_cname(sub)
        if cname:
            print(f"{sub} -> {cname}")

実行例:

pip install dnspython
python check_cname.py subdomains.txt > cnames.txt

防止策1: サービス削除時にCNAMEを同時削除する

当たり前だが徹底されていないことが多い。IaCで管理していれば一括削除できる。

# Terraform例: GitHub Pagesを削除するとCNAMEも消える
resource "aws_route53_record" "blog" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "blog.example.com"
  type    = "CNAME"
  ttl     = 300
  records = ["user.github.io"]
}
# このブロックを削除すれば自動でCNAMEも消える

防止策2: 定期的なゾーンファイル棚卸し

# Route53の全CNAMEレコードを取得して棚卸し
aws route53 list-resource-record-sets \
  --hosted-zone-id ZXXXXX \
  --query "ResourceRecordSets[?Type=='CNAME'].[Name,ResourceRecords[0].Value]" \
  --output table

各CNAMEの参照先が現在も有効なサービスかを月次で確認する。

防止策3: CAA recordでワイルドカード証明書の発行を制限

# 特定CAのみワイルドカード証明書を発行できるよう制限
example.com  CAA  0 issue "letsencrypt.org"
example.com  CAA  0 issuewild "letsencrypt.org"
example.com  CAA  0 iodef "mailto:security@example.com"

issuewild に信頼できるCA以外を記載しなければ、そのCA以外はワイルドカード証明書を発行できなくなる。攻撃者が乗っ取ったサブドメインでLet's Encrypt経由のワイルドカード証明書を取得しにくくなる。

まとめ

サブドメイン乗っ取りは「捨てたものの後始末」の問題である。IaCでDNSを管理し、サービス削除と同時にレコードを消す運用を徹底することが根本解決である。定期的にsubjackやnucleiでスキャンし、dangling CNAMEがないか確認する習慣を付けたい。

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?