web2-recon について
web2-reconは、バグバウンティ調査者向けにWeb資産を発見し、優先度付きURLリストへ絞り込むセキュリティスキルです。偵察手順に加え、対象のスコアリングや継続的な変更監視も扱います。
主な機能
- 01サブドメインと稼働ホストの発見
- 02URLと攻撃面の分類
- 03JavaScriptのエンドポイントと秘密情報の検査
- 04対象のスコアリングと中止判断
- 05サブドメインとコミットの監視
活用シーン
- 01脆弱性テスト前のURLリスト作成
- 02プログラムと攻撃面に基づく対象の優先順位付け
- 03新規資産とコミットの監視
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill web2-reconインストール後、Claude Code で/web2-reconを入力して読み込まれたか確認します。
詳細
WEB2 RECON PIPELINE
何もない状態から、ハンティングにすぐ使える優先順位付き URL リストを作成するまでの、アセット探索の全工程です。
セットアップ(初回のみ)
# 1. Set your Chaos API key (get free key at chaos.projectdiscovery.io)
export CHAOS_API_KEY="your-key-here"
# Add to ~/.zshrc or ~/.bashrc for persistence:
echo 'export CHAOS_API_KEY="your-key-here"' >> ~/.zshrc
# 2. Update nuclei templates (run weekly)
nuclei -update-templates
# 3. Configure subfinder with API keys for more sources
mkdir -p ~/.config/subfinder
cat > ~/.config/subfinder/config.yaml << 'EOF'
# Get free keys at: virustotal.com, securitytrails.com, censys.io, shodan.io
virustotal: [YOUR_VT_KEY]
securitytrails: [YOUR_ST_KEY]
censys_apiid: YOUR_CENSYS_ID
censys_secret: YOUR_CENSYS_SECRET
shodan: [YOUR_SHODAN_KEY]
EOF
# 4. Verify all tools installed
which subfinder httpx dnsx nuclei katana waybackurls gau dalfox ffuf anew gf interactsh-client
5 分ルール
5 分間の偵察で興味深いものが見つからなければ、次に移りましょう。成果のない攻撃対象に何時間も費やさないでください。
5 分で見切るサイン:
- すべてのサブドメインが 403 または静的なマーケティングページを返す
- URL に API エンドポイントが見当たらない
- 興味深いエンドポイントのパスを含む JavaScript バンドルがない
- nuclei の中・高深刻度の検出結果が 0 件
- フォーム、認証、ユーザーデータがない
標準的な偵察パイプライン
ハント前:まず必ず実行
TARGET="target.com"
# Step 0: Passive — crt.sh certificate transparency (no API key needed)
curl -s "https://crt.sh/?q=%.${TARGET}&output=json" \
| jq -r '.[].name_value' \
| sed 's/\*\.//g' \
| sort -u > /tmp/subs.txt
echo "[+] crt.sh: $(wc -l < /tmp/subs.txt) subdomains"
# Step 1: Chaos API (ProjectDiscovery — most comprehensive source)
curl -s "https://dns.projectdiscovery.io/dns/$TARGET/subdomains" \
-H "Authorization: $CHAOS_API_KEY" \
| jq -r '.[]' >> /tmp/subs.txt
echo "[+] Chaos returned $(wc -l < /tmp/subs.txt) subdomains"
# Step 2: subfinder (passive multi-source)
subfinder -d $TARGET -silent | anew /tmp/subs.txt
assetfinder --subs-only $TARGET | anew /tmp/subs.txt
echo "[+] Total subdomains after all sources: $(wc -l < /tmp/subs.txt)"
# Step 3: DNS resolution + live host check
cat /tmp/subs.txt | dnsx -silent | httpx -silent -status-code -title -tech-detect | tee /tmp/live.txt
echo "[+] Live hosts: $(wc -l < /tmp/live.txt)"
# Step 4: URL crawl
cat /tmp/live.txt | awk '{print $1}' | katana -d 3 -jc -kf all -silent | anew /tmp/urls.txt
# Step 5: Historical URLs
echo $TARGET | waybackurls | anew /tmp/urls.txt
gau $TARGET --subs | anew /tmp/urls.txt
echo "[+] Total URLs: $(wc -l < /tmp/urls.txt)"
# Step 6: Nuclei scan
nuclei -l /tmp/live.txt -t ~/nuclei-templates/ -severity critical,high,medium -o /tmp/nuclei.txt
整理されたディレクトリに出力
TARGET="target.com"
RECON_DIR="recon/$TARGET"
mkdir -p $RECON_DIR
# All outputs go here:
/tmp/subs.txt → $RECON_DIR/subdomains.txt
/tmp/live.txt → $RECON_DIR/live-hosts.txt
/tmp/urls.txt → $RECON_DIR/urls.txt
/tmp/nuclei.txt → $RECON_DIR/nuclei.txt
攻撃対象領域のトリアージ
URL リストから興味深いターゲットを見つける
# Parameters worth testing
cat /tmp/urls.txt | grep -E "[?&](id|user|file|path|url|redirect|next|src|token|key|api_key)=" | tee /tmp/interesting-params.txt
# API endpoints
cat /tmp/urls.txt | grep -E "/api/|/v1/|/v2/|/v3/|/graphql|/rest/|/gql" | tee /tmp/api-endpoints.txt
# File upload endpoints
cat /tmp/urls.txt | grep -E "upload|file|attachment|document|image|avatar|photo|media" | tee /tmp/uploads.txt
# Admin/internal paths
cat /tmp/urls.txt | grep -E "/admin|/internal|/debug|/test|/staging|/dev|/management|/console" | tee /tmp/admin-paths.txt
# Authentication endpoints
cat /tmp/urls.txt | grep -E "/oauth|/login|/auth|/sso|/saml|/oidc|/callback|/token" | tee /tmp/auth-paths.txt
gf パターン(迅速な分類)
# Install gf patterns: https://github.com/tomnomnom/gf
cat /tmp/urls.txt | gf xss | tee /tmp/xss-candidates.txt
cat /tmp/urls.txt | gf ssrf | tee /tmp/ssrf-candidates.txt
cat /tmp/urls.txt | gf idor | tee /tmp/idor-candidates.txt
cat /tmp/urls.txt | gf sqli | tee /tmp/sqli-candidates.txt
cat /tmp/urls.txt | gf redirect | tee /tmp/redirect-candidates.txt
cat /tmp/urls.txt | gf lfi | tee /tmp/lfi-candidates.txt
cat /tmp/urls.txt | gf rce | tee /tmp/rce-candidates.txt
JS 解析
SecretFinder(JS バンドル内の API キー、トークン)
# Activate venv
source ~/tools/SecretFinder/.venv/bin/activate
# Scan a single JS file
python3 ~/tools/SecretFinder/SecretFinder.py -i "https://target.com/static/js/main.js" -o cli
# Scan all JS URLs found in recon
cat /tmp/urls.txt | grep "\.js$" | head -50 | while read url; do
echo "=== $url ==="
python3 ~/tools/SecretFinder/SecretFinder.py -i "$url" -o cli 2>/dev/null
done
deactivate
LinkFinder(JS 内に隠されたエンドポイント)
source ~/tools/LinkFinder/.venv/bin/activate
# Single JS file
python3 ~/tools/LinkFinder/linkfinder.py -i "https://target.com/app.js" -o cli
# All pages (crawls JS from HTML)
python3 ~/tools/LinkFinder/linkfinder.py -i "https://target.com" -d -o cli
deactivate
ディレクトリのファジング
ffuf — 標準的なファジング
# Directory discovery on a live host
ffuf -u "https://target.com/FUZZ" \
-w ~/wordlists/common.txt \
-mc 200,201,204,301,302,307,401,403 \
-ac \
-t 40 \
-o /tmp/ffuf-dirs.json
# API endpoint discovery
ffuf -u "https://target.com/api/FUZZ" \
-w ~/wordlists/api-endpoints.txt \
-mc 200,201,204,301,302 \
-ac \
-t 20
# IDOR fuzzing with authenticated request
# Create req.txt with Authorization: Bearer TOKEN
ffuf -request /tmp/req.txt \
-request-proto https \
-w <(seq 1 10000) \
-fc 404 \
-ac \
-t 10
ターゲットのスコアリング — 続行/中止
時間をかける前にスコアを付けます。スコアが 4 未満なら見送ります。
| 基準 | 点数 |
|---|---|
| 最大報奨金が 5,000 ドル以上 | +2 |
| 大規模なユーザーベース(10 万人超)または金銭を扱う | +2 |
| プログラム開始から 60 日未満 | +2 |
| 複雑な機能:API、OAuth、ファイルアップロード、GraphQL | +1 |
| 最近のコード/機能の変更(GitHub、変更履歴) | +1 |
| 非公開プログラム(競争が少ない) | +1 |
| 自分が知っている技術スタック | +1 |
| ソースコードを入手可能 | +1 |
| 調査対象となる、過去に開示されたレポートがある | +1 |
4 未満: 見送る 4~5: ほかに有望なものがない場合のみ 6~8: 良好 — 1~3 日を費やす 9 以上: 非常に有望 — 最大 1 週間を費やす
調査開始前に見切るべきサイン
- 最大報奨金が 500 ドル未満 → 時間をかける価値がない
- 最近のレポートがすべて N/A または重複 → ほかのハンターに調査し尽くされている
- スコープが静的なマーケティングページのみ → 攻撃対象領域がない
- 従業員が 5 人未満で収益がない会社 → 支払いが期待できない
- ルールで予定しているバグの種類が明示的に除外されている
技術スタックの検出(2 分)
# Response headers reveal backend
curl -sI https://target.com | grep -iE "server|x-powered-by|x-aspnet|x-runtime|x-generator"
# Common signals:
# Server: nginx + X-Powered-By: PHP/7.4 → PHP backend
# Server: gunicorn OR X-Powered-By: Express → Python/Node.js
# X-Powered-By: ASP.NET → .NET
# Server: Apache Tomcat → Java
# X-Runtime: Ruby → Ruby on Rails
# Framework from JS bundle paths:
# /_next/static/ → Next.js
# /static/js/main.chunk.js → CRA (React)
# /packs/ → Ruby on Rails + Webpacker
# /__nuxt/ → Nuxt.js (Vue)
スタック → 優先して狙うバグの種類
| スタック | 最初に狙うもの | 次に狙うもの |
|---|---|---|
| Ruby on Rails | Mass assignment | IDOR(:id ルート) |
| Django | IDOR(ModelViewSet、オブジェクト権限なし) | SSTI(mark_safe) |
| Flask | SSTI(render_template_string) | SSRF(requests ライブラリ) |
| Laravel | Mass assignment($fillable) | IDOR(Eloquent、所有者確認なし) |
| Express(Node.js) | プロトタイプ汚染 | パストラバーサル |
| Spring Boot | Actuator エンドポイント(/actuator/env) | SSTI(Thymeleaf) |
| ASP.NET | ViewState のデシリアライズ | オープンリダイレクト(ReturnUrl) |
| Next.js | Server Actions 経由の SSRF | redirect() 経由のオープンリダイレクト |
| GraphQL | イントロスペクション → mutation の認証バイパス | node(id:) 経由の IDOR |
| WordPress | プラグインの SQLi | REST API の認証バイパス |
継続的な監視のセットアップ
ターゲットごとに一度設定します。ほかのハンターより先にアラートを受け取れます。
新しいサブドメインのアラート(日次 cron)
#!/bin/bash
TARGET="target.com"
KNOWN="/tmp/$TARGET-subs-known.txt"
subfinder -d $TARGET -silent > /tmp/$TARGET-subs-fresh.txt
curl -s "https://dns.projectdiscovery.io/dns/$TARGET/subdomains" \
-H "Authorization: $CHAOS_API_KEY" \
| jq -r '.[]' >> /tmp/$TARGET-subs-fresh.txt
# Diff against known
NEW=$(comm -23 <(sort /tmp/$TARGET-subs-fresh.txt) <(sort $KNOWN 2>/dev/null))
if [ -n "$NEW" ]; then
echo "NEW SUBDOMAINS: $NEW"
echo "$NEW" >> $KNOWN
fi
# Schedule: crontab -e → 0 8 * * * /bin/bash ~/monitors/subs-watch.sh
GitHub コミットの監視
#!/bin/bash
REPO="TargetOrg/target-app"
LAST_SHA="/tmp/$REPO-last-sha.txt"
CURRENT=$(curl -s "https://api.github.com/repos/$REPO/commits?per_page=1" | jq -r '.[0].sha')
KNOWN=$(cat $LAST_SHA 2>/dev/null)
if [ "$CURRENT" != "$KNOWN" ]; then
echo "New commit on $REPO: $CURRENT"
echo $CURRENT > $LAST_SHA
# Get changed files
curl -s "https://api.github.com/repos/$REPO/commits/$CURRENT" \
| jq -r '.files[].filename' | grep -E "auth|middleware|route|permission|role|admin"
fi
# Schedule: */30 * * * * /bin/bash ~/monitors/github-watch.sh
ポートスキャン(省略されがちですが、省略しないでください)
# naabu — fast port scanner from ProjectDiscovery
# Finds non-standard ports: 8080, 8443, 3000, 8888, 9000, etc.
cat /tmp/live.txt | awk '{print $1}' | naabu -port 80,443,8080,8443,3000,4000,5000,8000,8888,9000,9090,9200,6379 -silent | tee /tmp/open-ports.txt
# Why this matters: admin panels, debug services, internal APIs often run on alt ports
# Example wins: :8080/actuator/env (Spring Boot), :9200/_cat/indices (Elasticsearch), :6379 (Redis)
JS バンドル内のシークレットスキャン
# trufflehog — high-signal secret detection with entropy analysis
# Scans JS files and git repos
pip install trufflehog3 2>/dev/null || true
trufflehog filesystem --only-verified recon/$TARGET/ 2>/dev/null
# SecretFinder — manual JS bundle scan (already in tools/)
source ~/tools/SecretFinder/.venv/bin/activate
cat /tmp/urls.txt | grep "\.js$" | head -100 | while read url; do
python3 ~/tools/SecretFinder/SecretFinder.py -i "$url" -o cli 2>/dev/null
done
deactivate
# Quick grep for common patterns in downloaded JS
wget -q -r -l 1 -A "*.js" -P /tmp/js-files/ "https://$TARGET" 2>/dev/null
grep -rn "api_key\|apiKey\|client_secret\|access_token\|private_key\|AWS_SECRET\|AKIA" /tmp/js-files/ 2>/dev/null
ターゲットの GitHub Dork 検索
# Search GitHub for hardcoded secrets before hunting the app
TARGET_ORG="TargetOrgName" # Check their GitHub org
# Useful dorks (search on github.com):
# org:TARGET_ORG password
# org:TARGET_ORG api_key
# org:TARGET_ORG "Authorization: Bearer"
# org:TARGET_ORG .env
# org:TARGET_ORG "BEGIN RSA PRIVATE KEY"
# CLI with gh (GitHub CLI):
gh search code "api_key" --owner "$TARGET_ORG" --json path,repository 2>/dev/null | jq '.'
gh search code "password" --owner "$TARGET_ORG" --json path,repository 2>/dev/null | head -20
# GitDorker (if installed):
python3 ~/tools/GitDorker/GitDorker.py -t GITHUB_TOKEN -d ~/tools/GitDorker/Dorks/alldorksv3 -q "$TARGET" -org
30 分間の偵察プロトコル
0~5 分:プログラムのページを読む
Note:
- ALL in-scope assets (every domain listed)
- Out-of-scope list (read carefully — common trap)
- Safe harbor statement
- Impact types accepted (some exclude "low")
- Average bounty amount (signals program generosity)
5~15 分:アセット探索
上記の標準的なパイプラインを実行します。live.txt の出力を重点的に確認します。
15~25 分:攻撃対象領域のマッピング
gf パターンと、上記の興味深いパラメーターを対象とした grep を実行します。
25~30 分:手動で調査
Burp Suite を開きます。プロキシを有効にしてアプリを閲覧します。
- アカウントを登録する
- 主なユーザー操作(リソースの作成/読み取り/更新/削除)を行う
- Burp の履歴にあるすべての API 呼び出しを記録する
- URL リストにないエンドポイントを探す
30 分後:優先順位を決める
Priority 1: API endpoints with ID parameters → IDOR candidates
Priority 2: File upload features → XSS/RCE candidates
Priority 3: OAuth/SSO flows → auth bypass candidates
Priority 4: Search/filter with user input → SQLi/SSRF/SSTI candidates
Priority 5: Admin/debug endpoints → auth bypass candidates
ツールチェーンのフォールバック(dnsx / httpx がクラッシュする場合)
projectdiscovery の Go バイナリ(dnsx、httpx、naabu)は、cgo とシステムリゾルバーの相互作用により、macOS arm64 でまれに SIGSEGV が発生します。インストール方法にかかわらず、クラッシュ時のシグネチャは同一です。brew install と go install github.com/projectdiscovery/<tool>@latest のどちらでインストールしても、同じアドレスでセグフォルトが発生するバイナリが生成されます。実際のエンゲージメントで使用する前に、一度スモークテストを実施してください。
dnsx -version # if SIGSEGV: use the dig fallback below
httpx -version # if SIGSEGV: use the curl fallback below
dnsx → dig へのフォールバック
# Replaces: dnsx -l subs.txt -a -resp -silent
while read s; do
ips=$(dig +short +tries=1 +time=3 "$s" \
| grep -E '^[0-9.]+$' \
| paste -sd, -)
[ -n "$ips" ] && echo "$s|$ips"
done < subs.txt
httpx → curl へのフォールバック
# Replaces: httpx -l subs.txt -silent -status-code -title -tech-detect
while read s; do
resp=$(curl -s -L -m 5 -o /tmp/body \
-w "%{http_code}|%{url_effective}|%{header_server}" \
"https://$s")
code=$(echo "$resp" | cut -d'|' -f1)
if [ "$code" != "000" ]; then
title=$(grep -oE '<title[^>]*>[^<]*</title>' /tmp/body | head -1 | sed 's/<[^>]*>//g')
echo "$s|$resp|$title"
fi
done < subs.txt
トレードオフ: 逐次処理か並行処理か。フォールバックでは約 24 個のサブドメインを 14 秒で処理します。同じ処理を httpx のデフォルトの 50 スレッドで実行すると、2~3 秒で完了します。VDP 規模の偵察(サブドメインが 100 個未満)なら、フォールバックで問題ありません。大規模な偵察(1000 個以上)の場合は、まずツールチェーンを修正してください。
HackerOne 自身の VDP で検証済みです。詳細は docs/verification/recon-hackerone-vdp.md を参照してください。
API 仕様/Swagger/OpenAPI の発見(2024~2026 年の攻撃対象領域)
API 仕様のエンドポイントは、最新の .NET/Node/Python/Java バックエンドにおいて、偵察の効果が最も高い対象です。仕様には、すべてのエンドポイント、HTTP メソッド、パラメーター名・型・形式、モデル、検証ルールが記載されており、JSON 形式の完全な攻撃マップとなります。本番環境でもデフォルトのルートが有効なままになっていることはよくあります。このワードリストをディレクトリファジングのフェーズ(標準の common.txt による検査の後)に追加してください。
デフォルトの探索パスのワードリスト(swagger-paths.txt に貼り付けてください)
# NSwag / Swashbuckle (ASP.NET Core)
/swagger
/swagger/
/swagger/index.html
/swagger/ui/index.html
/swagger/v1/swagger.json
/swagger/v2/swagger.json
/swagger/v3/swagger.json
/swagger/docs/v1
/swagger/docs/v2
/swagger-ui
/swagger-ui/
/swagger-ui.html
/swagger-resources
/swagger-resources/configuration/ui
/nswag
/nswag/index.html
/api/swagger
/api/swagger.json
/api/swagger/v1/swagger.json
/api/openapi
/api/openapi.json
/api/v1/swagger.json
/api/v2/swagger.json
/api-docs
/api-docs/swagger.json
# OpenAPI generic
/openapi
/openapi.json
/openapi.yaml
/openapi.yml
/openapi/v1.json
/openapi/v2.json
/openapi/v3.json
/.well-known/openapi.json
# Java / Spring (Springfox / springdoc)
/v2/api-docs
/v3/api-docs
/v3/api-docs.yaml
/v3/api-docs/swagger-config
/swagger-ui/index.html
# Python (FastAPI / Flask-RESTPlus / Connexion / DRF)
/docs
/docs/
/redoc
/redoc/
/openapi.json
/swagger.json
/swagger/?format=openapi
/swagger.yaml
# Express / Node / Hapi
/api-docs
/api-docs.json
/swagger.json
/swagger-stats
/graphql-docs
# GraphQL adjacent (often co-located)
/graphql
/graphiql
/playground
/altair
/voyager
/graphql/console
/graphql-explorer
# ReDoc / RapiDoc / Stoplight / alt UIs
/redoc
/redoc.html
/redoc-ui.html
/rapidoc
/rapidoc.html
/stoplight
/elements
# Misc / dev-leftover
/actuator
/actuator/openapi
/actuator/mappings
/q/openapi
/q/swagger-ui
/docs/swagger.json
/api/v1/docs
/api/v2/docs
/internal/swagger
/admin/swagger
/management/swagger
標準パイプラインとの統合
# After live-hosts.txt is built (Phase 1 / 2), run:
ffuf -w swagger-paths.txt -u "https://FUZZ.target.com" -mc 200,302 -fs 0 -t 50 -o swagger-hits.json
# Or with httpx for content-aware filtering:
httpx -l live-hosts.txt -path swagger-paths.txt -mc 200 -mr "swagger|openapi" -json | tee swagger-hits.jsonl
# For every hit:
jq '.paths | keys' swagger.json > endpoints.txt
jq '.components.schemas' swagger.json > schemas.json # mass-assignment field candidates
偵察からハンティングへの引き継ぎで重要な理由
- 仕様 → 大規模な IDOR/BOLA 検査 —
jq '.paths | keys' swagger.jsonの出力を、ユーザーごとのテストにおけるAutorize/ffufの入力リストとして使用します。 - 仕様 → マスアサインメントのペイロード構築 —
components.schemas.UserUpdateDtoには、isAdmin、emailVerified、tenantId、roleが列挙されています。 - 仕様 → 隠しエンドポイントの発見 —
/internal/*、/debug/*、/v0/*、/legacy/*などのルートが文書化されている一方、認証による保護が設定されていません。 - 仕様 → インジェクション攻撃クラスのシード作成 — 各パラメーターの型、形式、列挙値、最大長が分かるため、ペイロードが検証を通過してシンクに到達します。モデルバインダーがコントローラーのロジック実行前に不正な入力を拒否する ASP.NET Core では、特に有効です。
ツール
kiterunner— OpenAPI 仕様をネイティブに取り込み、API に対するリクエストを生成します。sj(Swagger Jacker)— Swagger 仕様の悪用に特化したツールです。apidetector(brinhosa)— Swagger UI の大規模スキャナーです。XSSwagger(vavkamil)— 脆弱なバージョンの Swagger UI を検出します(CVE-2018-25031 系)。nuclei -t http/exposures/apis/— デフォルトの仕様パスを対象とする組み込みテンプレートです。
アンチパターンについての注意
/swagger が 404/403 でも、仕様が公開されていないとは限りません。多くの .NET プロジェクトでは、仕様を /swagger ではなく /api/swagger/v1/swagger.json に配置しています。ルートだけでなく、必ずパスの一覧全体を検査してください。
攻撃チェーンの完全な分析は、hunt-api-misconfig → NSwag / Swagger / OpenAPI Spec Exposure にあります。
関連するスキルとチェーン
offensive-osint— 基本的なパイプラインを超える具体的なプローブ/ワードリスト/正規表現が必要な場合に使用します。ワークフローの基本要素:このスキルは URL セットを生成し、offensive-osintはその URL セットに適用するシークレット用正規表現、GraphQL/Swagger のパス、アイデンティティファブリックのプローブを提供します。osint-methodology— 発見した内容の重大度を評価する基準が必要な場合に使用します。ワークフローの基本要素:偵察によってsubdomains.txt/live-hosts.txt/urls.txtが出力された後、各アセットをosint-methodologyの調査結果評価基準に照らしてスコアリングし、調査結果として報告するものと、アセットグラフにとどめるものを決定します。hunt-subdomain— 偵察で古い CNAME/ぶら下がり DNS が見つかった場合に使用します。ワークフローの基本要素:subdomains.txt内で CNAME が S3/GitHub Pages/Heroku/Shopify/Azure を指すサブドメインは、テイクオーバーの検証のために自動的にhunt-subdomainに振り分けます。security-arsenal— URL セットがgfで分類され、アクティブテストの準備ができた場合に使用します。ワークフローの基本要素:gf xss/ssrf/sqli/idorの出力名を、security-arsenalのペイロードライブラリに対するペイロード分類クエリとして使用します。bb-methodology— 偵察が完了し、フェーズ 1 からフェーズ 2(マッピング)に移行する場合に使用します。ワークフローの基本要素:稼働中のホストと URL セットをbb-methodologyのフェーズ 2 に戻し、エンドポイントのマッピングとフェーズ 3 の脆弱性発見先の振り分けを行います。
オペレーター向けメモ(Claude-BugHunter)
実際のエンゲージメントから得られた、ベンダー提供の基盤への 2026 年固有の追加事項です。 実際に許可を得たエンゲージメントと、このリポジトリの 31 以上のスキル領域にわたるライブテストでのフェーズ 2 検証から得られた知見です。上流のパイプラインが WHAT を扱うのに対し、 このレイヤーは「うまくいく場合」と「うまくいかない場合」を扱います。
TLD をまたぐピボットの注意事項
フェーズ 2C の HackerOne VDP 偵察では、hackerone.com(サブドメイン 24 個)から、JS バンドル内の参照で見つかった関連 TLD hacker.one(さらに 12 個のサブドメイン)へと範囲を広げました。*.target.com だけを列挙するオペレーターは、対象が別ドメインで正当に運用している攻撃対象領域を見落とします。
JS バンドル内で、関連する可能性のある兄弟 TLD を必ず grep してください。
# pull all JS, grep for sibling-TLD candidates
for url in $(cat live-hosts.txt); do
curl -s "$url" | grep -oE 'src="[^"]+\.js"' | sed 's/src="//;s/"//'
done | sort -u > js-urls.txt
# then on each JS file
for j in $(cat js-urls.txt); do
curl -s "$j" | grep -oE '[a-z0-9.-]+\.(io|app|one|dev|test|cloud|ai|co)' | sort -u
done | sort -u > sibling-tld-candidates.txt
よくある兄弟 TLD のパターン:target.com → target.io / target.app / target.one / target.dev / target.test / target-corp.com / target-cdn.net。兄弟 TLD を対象範囲内として扱う前に、WHOIS で確認するか、証明書チェーンが同じ内部 CA を信頼しているかを必ず確認してください。
2026 年のサブドメイン用ワードリストの優先順位
2024〜2026 年のデータセットにおいて、企業の VDP に対するヒット率が高かった発見用プレフィックスの上位:
mta-sts.* api.* docs.*
dev-* staging-* *-qa
*-stage *-uat events.*
portal.* customer.* partner.*
vendor.* internal-* admin-*
employee-* hr.* jobs.*
sso.* auth.* id.*
内部向けに見えるサブドメインは、マーケティングサイトよりも多くの攻撃対象領域を露呈することがよくあります。partner.target.com や vendor-portal.target.com は、「信頼された」外部ユーザー向けに範囲を限定しているため、メインアプリより認証が弱いケースが頻繁にあります。標準的な subfinder の実行が完了したら、必ずロングテールのワードリストにもプローブを送ってください。
稼働中ホストのプローブ:スタックをすばやく特定する方法
curl -sI <host> のヘッダーでフィンガープリントの 80% がわかります。
Server:— apache/nginx/cloudflare/kestrel(= .NET Core)/openresty/envoyX-Powered-By:— PHP のバージョン、ASP.NET のバージョン、Express.jsX-Drupal-Cache、X-Generator: Drupal 9— DrupalX-Generator: WordPress— WordPressVia:— CDN チェーン(1.1 varnish、1.1 cloudfront)Set-Cookie:の名前 —JSESSIONID(Java)、PHPSESSID(PHP)、ASP.NET_SessionId(.NET)、connect.sid(Express)、laravel_session(Laravel)
JS バンドルのファイル名のパターン:
/_next/static/= Next.js/_nuxt/= Nuxt/assets/static/とハッシュ付きファイル名 = Vite/static/js/main.*.chunk.js= Create React Appruntime.*.js + polyfills.*.js + main.*.js= Angular CLI
偵察開始後の最初の 10 秒で、スタックの見当をつけられるはずです。その後はターゲットを絞り込みます。フィンガープリントに矛盾がある場合(Server は nginx を示し、Set-Cookie は ASP.NET を示すなど)、リバースプロキシのフロントエンドを見つけたことになります。後でスマグリング/キャッシュ攻撃に使えるよう、オリジンアプリを記録してください。
GitHub Pages の 404 とテイクオーバーシグナルの違い
運用担当者がよく間違える重要な区別:
- 「Page not found · GitHub Pages」 で HTTP 404 の場合、リポジトリは存在しています — テイクオーバーではありません。
- 「There isn't a GitHub Pages site here」 の場合、リポジトリは削除されています — テイクオーバーの候補です。
CloudFront でも同じ区別があります:
- 「Error - 404」 で
Server: CloudFront= ディストリビューションは存在し、オリジンが 404 を返している — テイクオーバーではありません。 - 「The request could not be satisfied」 で
X-Cache: Error from cloudfront= オリジンが完全に存在しない — テイクオーバーの可能性があります。
Phase 2C では両方のパターンを実際に検証しました。テイクオーバーの所見を記録する前に、必ず正確なレスポンスボディの文字列を確認してください — テイクオーバースキャナーツール(subzy、subjack)は複数のフィンガープリントでマッチするため、「まだ所有されているが空なだけ」のケースで頻繁に誤検知します。
ツールチェーンのフォールバック
このファイルの Phase 2C の追記で既に扱っています。簡単な再掲: dnsx/httpx は macOS arm64 でセグメンテーション違反を起こすことがあります。dig+curl のフォールバックは 100 ホスト未満の実行なら約 14 秒で動作します。フォールバックで同じ URL セットに到達できるのに、Go バイナリのパニックのデバッグに 1 時間を費やさないでください。