mcpField
V
vhost-enumeration

vhost-enumeration

github.com/uphiagoセキュリティ1.3k44 回インストール8 週間前に更新
リポジトリ

vhost-enumeration について

対象 IP に Host ヘッダーを送って隠れた仮想ホストを探すセキュリティスキルです。レスポンスの絞り込み、ホスト名の検証、証明書や逆引き DNS の確認を扱います。

主な機能

  1. 01ffuf による Host ヘッダーのファジング
  2. 02デフォルトレスポンスの除外
  3. 03curl によるホスト名の検証
  4. 04TLS 証明書の SAN から名前を抽出
  5. 05PTR レコードの利用とホスト内容の比較

活用シーン

  1. 01サブドメイン列挙で見つからなかった内部ホスト名の発見
  2. 02対象 IP を共有するサービスの特定
  3. 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 からアクセスできないことがあります。 内部ネットワークへのアクセスが必要な場合があります。

検証

  1. ffuf が、キャリブレーション済みのデフォルトとは異なるステータスコードとレスポンスサイズを返す。
  2. 発見した Host ヘッダーを指定した curl が、(デフォルトページではなく)意味のあるコンテンツを返す。
  3. 発見したホスト名が公開サブドメインのリストに含まれておらず、これまで未知だったものである。
  4. SSL 証明書の SAN フィールドで、そのホスト名がこのサーバーに属することを確認する。
  5. スクリーンショットを撮り、別個のアプリケーションまたはサービスであることを確認する。

関連スキル

  • subdomain-enumeration — DNS ワードリストと既存のサブドメインを生成します。
  • origin-ip-discovery — VHOST スキャンが必要なオリジン IP を見つけます。
  • web-enumeration — VHOST が見つかったら、ディレクトリとエンドポイントをファジングします。

コメント