vhost-enumeration について
対象 IP に Host ヘッダーを送って隠れた仮想ホストを探すセキュリティスキルです。レスポンスの絞り込み、ホスト名の検証、証明書や逆引き DNS の確認を扱います。
主な機能
- 01ffuf による Host ヘッダーのファジング
- 02デフォルトレスポンスの除外
- 03curl によるホスト名の検証
- 04TLS 証明書の SAN から名前を抽出
- 05PTR レコードの利用とホスト内容の比較
活用シーン
- 01サブドメイン列挙で見つからなかった内部ホスト名の発見
- 02対象 IP を共有するサービスの特定
- 03証明書とレスポンスデータによる候補仮想ホストの検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill vhost-enumerationインストール後、Claude Code で/vhost-enumerationを入力して読み込まれたか確認します。
詳細
仮想ホストの列挙
Host ヘッダーをファジングして、IP アドレス上の隠れた仮想ホストを見つけます。多くのサーバーは特定のドメイン名にのみ応答するため、標準的なサブドメイン列挙では検出されません。VHOST ファジングにより、同じ IP を共有しながら異なるホスト名に応答する内部サービス、開発環境、管理パネルを見つけられます。
使用する場面
skill_view(name='origin-ip-discovery')またはskill_view(name='port-service-discovery')で対象 IP のリストを取得している場合。- 不明な Host ヘッダーに対して、サーバーがデフォルトページや空白ページを返す場合。
- サブドメイン列挙では、内部専用のホスト名を見逃している可能性がある場合。
- IP の SSL 証明書の SAN フィールドに複数のドメイン名が記載されている場合。
- リバースプロキシの背後にある内部サービスをマッピングする必要がある場合。
前提条件
- curl、ffuf、dnsx、httpx を備えた
terminal。 - ホスト名のファジングに使う DNS ワードリスト。
- 対象 IP アドレスのリスト。
簡易検出
# Basic VHOST fuzz on a single IP
ffuf -u http://TARGET_IP \
-w /path/to/wordlist.txt \
-H "Host: FUZZ.target.com" \
-fs 0 -mc 200,301,302,401,403
手順
フェーズ 1 — Host ヘッダーのファジング
# Fuzz for virtual hosts matching the target domain pattern
ffuf -u http://TARGET_IP \
-w $DNS_WORDLIST \
-H "Host: FUZZ.target.com" \
-fs DEFAULT_RESPONSE_SIZE \
-mc 200,301,302,401,403 \
-o vhost_ffuf.json
# HTTPS variant
ffuf -u https://target.com \
-w $DNS_WORDLIST \
-H "Host: FUZZ.target.com" \
-mc 200,301,302,401,403
# Fuzz multiple IPs with a wordlist
cat unique_ips.txt | while read ip; do
ffuf -u "http://$ip" \
-w $DNS_WORDLIST \
-H "Host: FUZZ.target.com" \
-fs 0 -mc 200,301,302 -o "vhost_$ip.json"
sleep 0.5
done
フェーズ 2 — レスポンスのフィルタリング
# Auto-calibrate: ffuf detects default response size and filters it out
ffuf -u http://TARGET_IP \
-w $DNS_WORDLIST \
-H "Host: FUZZ.target.com" \
-ac -sf -s \
-mc 200
# Manual calibration: find the default response size first
curl --max-time 30 --connect-timeout 10 -s http://TARGET_IP -H "Host: nonexistentxxxxx12345.target.com" | wc -c
# Use that size as -fs filter
フェーズ 3 — VHOST の対象へのアクセス
# Method 1 — direct curl with Host header
curl --max-time 30 --connect-timeout 10 -H "Host: dev.target.com" http://TARGET_IP
# Method 2 — /etc/hosts injection for browser access
echo "TARGET_IP dev.target.com internal.target.com admin.target.com" | sudo tee -a /etc/hosts
# Then open http://dev.target.com in browser
# Method 3 — httpx with custom host resolution
echo "http://dev.target.com" | httpx -silent
フェーズ 4 — SSL 証明書の SAN 列挙
# Extract hostnames from SSL certificate
echo | openssl s_client -connect TARGET_IP:443 -servername target.com 2>/dev/null \
| openssl x509 -noout -text \
| grep -Eo 'DNS:[^,\s]+' | cut -d: -f2 | sort -u
# Batch: extract hostnames from all discovered IPs
cat unique_ips.txt | while read ip; do
echo | timeout 5 openssl s_client -connect $ip:443 2>/dev/null \
| openssl x509 -noout -text 2>/dev/null \
| grep -Eo 'DNS:[^,\s]+' | cut -d: -f2 | sort -u >> ssl_hostnames.txt
sleep 0.5
done
# Check which of those hostnames resolve to the target
cat ssl_hostnames.txt | dnsx -silent -a -resp-only | sort -u
フェーズ 5 — IP 範囲の PTR 逆引き DNS
# If you have IP ranges, resolve PTR records to find hostnames
echo "10.0.0.0/23" | dnsx -silent -resp-only -ptr
# Batch on multiple CIDR ranges
cat cidr_ranges.txt | mapcidr -silent | dnsx -ptr -resp-only -silent > ptr_domains.txt
フェーズ 6 — コンテンツの差分比較
# For each found VHOST, take a screenshot for visual triage
cat found_vhosts.txt | gowitness file -f - --no-http -P ./vhost_screenshots/
# Compare content across hosts — different content = different service
for host in $(cat found_vhosts.txt); do
curl --max-time 30 --connect-timeout 10 -sk "http://TARGET_IP" -H "Host: $host" | md5sum
sleep 0.3
done | sort
注意点
- ワイルドカード DNS は、どの Host ヘッダーに対しても有効な HTTP レスポンスを返します。 自動キャリブレーション(
-ac)を使用し、手動で確認してください。 - デフォルトの仮想ホストは、未知の名前に対して汎用ページを返すことがあります。 存在しないことがわかっているホスト名を使って
-fsをキャリブレーションしてください。 - SSL/TLS が原因で、SNI を指定しないとコンテンツを比較できません。 ホスト名ごとに
openssl s_client -servernameを使用してください。 - Host ヘッダーを何でも受け入れるサーバーもあります。 誤検知につながるため、curl で見つかったホストをそれぞれ手動で確認してください。
- 内部専用サービスには、使用中の IP からアクセスできないことがあります。 内部ネットワークへのアクセスが必要な場合があります。
検証
- ffuf が、キャリブレーション済みのデフォルトとは異なるステータスコードとレスポンスサイズを返す。
- 発見した Host ヘッダーを指定した curl が、(デフォルトページではなく)意味のあるコンテンツを返す。
- 発見したホスト名が公開サブドメインのリストに含まれておらず、これまで未知だったものである。
- SSL 証明書の SAN フィールドで、そのホスト名がこのサーバーに属することを確認する。
- スクリーンショットを撮り、別個のアプリケーションまたはサービスであることを確認する。
関連スキル
subdomain-enumeration— DNS ワードリストと既存のサブドメインを生成します。origin-ip-discovery— VHOST スキャンが必要なオリジン IP を見つけます。web-enumeration— VHOST が見つかったら、ディレクトリとエンドポイントをファジングします。
コメント
Markdown 対応