mcpField
W
web2-recon

web2-recon

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

web2-recon について

web2-reconは、バグバウンティ研究者向けのWeb資産調査ガイドです。発見から攻撃対象領域の分類、対象の評価までをまとめ、優先順位付きURLリストの作成を支援します。

主な機能

  1. 01サブドメインと稼働ホストの発見
  2. 02URLとAPIエンドポイントの分類
  3. 03JavaScriptのエンドポイントと秘密情報の確認
  4. 04ディレクトリファジングとポートスキャン
  5. 05対象の評価と継続監視

活用シーン

  1. 01バグバウンティ対象の初期調査
  2. 02URL一覧からAPIやパラメーターを抽出
  3. 03JavaScriptバンドル内のエンドポイントと秘密情報の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/uphiago/recon-skills --skill web2-recon

インストール後、Claude Code で/web2-reconを入力して読み込まれたか確認します。

詳細

WEB2 リコンパイプライン

何もない状態から、ハンティングに使える優先順位付き 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 alltools 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 --max-time 30 --connect-timeout 10 -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 --max-time 30 --connect-timeout 10 -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 未満なら見送ってください。

基準ポイント
最大報奨金が $5K 以上+2
ユーザーベースが大きい(>100K)、または金銭を扱う+2
プログラム開始から 60 日未満+2
複雑な機能:API、OAuth、ファイルアップロード、GraphQL+1
最近のコード/機能の変更(GitHub、変更履歴)+1
非公開プログラム(競争が少ない)+1
使用経験のある技術スタック+1
ソースコードが入手可能+1
調査対象となる過去の公開レポート+1

4 未満: 見送る 4~5: より良い対象がない場合のみ 6~8: 良好 — 1~3 日費やす 9 以上: 非常に良好 — 最大 1 週間費やす

ダイブ前に見切るべきサイン
  1. 最大報奨金が $500 未満 → 時間を費やす価値はありません
  2. 最近のレポートがすべて N/A または重複 → ハンターが飽和しています
  3. スコープが静的なマーケティングページのみ → 攻撃対象領域がありません
  4. 会社の従業員が 5 人未満で収益がない → 支払いが期待できません
  5. ルールで、予定しているバグクラスが明示的に除外されている

技術スタックの検出(2 分)

# Response headers reveal backend
curl --max-time 30 --connect-timeout 10 -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マスアサインメントIDOR(:id ルート)
DjangoIDOR(ModelViewSet、オブジェクト権限なし)SSTI(mark_safe)
FlaskSSTI(render_template_string)SSRF(requests ライブラリ)
Laravelマスアサインメント($fillable)IDOR(Eloquent、所有権確認なし)
Express(Node.js)プロトタイプ汚染パストラバーサル
Spring BootActuator エンドポイント(/actuator/env)SSTI(Thymeleaf)
ASP.NETViewState のデシリアライゼーションオープンリダイレクト(ReturnUrl)
Next.jsServer Actions 経由の SSRFredirect() 経由のオープンリダイレクト
GraphQLイントロスペクション → ミューテーションの認証バイパスnode(id:) 経由の IDOR
WordPressプラグインの SQLiREST API の認証バイパス

継続的な監視の設定

対象ごとに一度設定します。他のハンターより先にアラートを受け取れます。

新しいサブドメインのアラート(毎日の cron)
#!/bin/bash
TARGET="target.com"
KNOWN="/tmp/$TARGET-subs-known.txt"

subfinder -d $TARGET -silent > /tmp/$TARGET-subs-fresh.txt
curl --max-time 30 --connect-timeout 10 -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 --max-time 30 --connect-timeout 10 -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 --max-time 30 --connect-timeout 10 -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
# nmap often fails with "nse_main.lua not found" on minimal containers — naabu works.
# 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)
生のポート接続テスト(naabu を利用できない場合)
# Quick single-port check via bash /dev/tcp — works anywhere bash is available
for port in 22 80 443 3306 5432 6379 8080 8081 8443 27017; do
  timeout 3 bash -c "echo >/dev/tcp/$TARGET/$port" 2>&1 && echo "PORT $port OPEN" || echo "PORT $port CLOSED/FILTERED"
done

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 intools/)
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
JS バンドルからの API キー抽出(BusyBox 対応の代替手段)

BusyBox grep は -P(PCRE/Perl 正規表現)をサポートしていません。Alpine コンテナ内の JS バンドルで正規表現マッチングを行うには Python3 を使用してください。

# Extract Firebase API keys from JS bundle
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/static/js/main.*.js" 2>/dev/null | python3 -c "
import sys, re
content = sys.stdin.read()
for k in re.findall(r'AIza[0-9A-Za-z_-]{35}', content):
    print(f'Firebase API Key: {k}')
for m in re.findall(r'(?:apiUrl|apiKey|authDomain|databaseURL|projectId)[\"\']?\s*[:=]\s*[\"]([^\"\']+)[\"]', content):
    print(f'Config: {m}')
for u in re.findall(r'https?://[a-zA-Z0-9._-]+\.(?:firebaseio|firestore|googleapis|herokuapp)\.com[^\"\\s,]*', content):
    print(f'URL: {u}')
for s in re.findall(r'(?:secret|jwt[_-]?secret|token)[\"\']?\s*[:=]\s*[\"]([a-zA-Z0-9_\-]{16,})[\"]', content):
    print(f'Potential secret: {s}')
" 2>/dev/null

# For React SPAs with chunked bundles — find the main bundle first
main_js=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET:8080/" 2>/dev/null | grep -Eo 'src="([^"]+\.js)"' | sed 's/src="//;s/"//' | head -1)
[ -n "$main_js" ] && curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET:8080/$main_js" | python3 -c "
import sys, re
content = sys.stdin.read()
for m in re.findall(r'https?://[^\"\\s,;\\)]+', content):
    if '://' in m and not 'fonts.' in m:
        print(f'URL: {m}')
for m in re.findall(r'apiUrl[\"\\']?\s*[:=]\s*[\"\\']([^\"\\']+)[\"\\']', content):
    print(f'apiUrl: {m}')
" 2>/dev/null

この手法により、ナビゲーションや DNS の命名規則には現れない、標準以外のポート上の API バックエンドを発見できる場合があります。

対象の GitHub 検索演算子の活用

# 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 分間のリコンプロトコル

デュアルトラック並行偵察(複数ターゲットの一括調査で有効性を実証済み)

複数のセクターにまたがる15~20以上のターゲットをテストする場合は、デュアルトラック方式を使用します。

トラック1 — 手動での迅速なプローブ(トラック2の実行中に行います)

  1. 各ドメインに対して curl --max-time 10 --connect-timeout 5 -sI を実行し、生存確認とサーバーヘッダーの取得を行います(5ドメインあたり約30秒)。
  2. 有望なシグナルをすぐに確認します。WordPress の link ヘッダー、CORS オリジン、興味深い Cookie などです。
  3. 興味深いドメインについて、記憶が新しいうちに subfinder を実行します。
  4. 生存しているサブドメイン(app.、dashboard.、staging. など)をすぐに追跡します。

トラック2 — 自動スキャナー(バックグラウンド)

  • 適切な遅延を設定し、5つの並列タスクを実行する Python スキャナーを起動します。
  • スキャナーが体系的な調査を行います。すべてのドメインについて、WP 検出、CORS テスト、機密ファイルの確認、サブドメイン列挙を行います。
  • 定期的に進捗を確認します。完了するころには、重要度の高い調査結果をすでに把握できています。

この方法が有効な理由:

  • 手動プローブにより、最初の5分で価値の高いターゲット(CRITICAL な CORS、WP ユーザー、公開されたステージング環境)を発見できます。
  • 自動スキャナーが残りを検証するため、応答のないターゲットに注意を費やさずに済みます。
  • 手動で見つけたサブドメインは、スキャナーの実行中にすぐにプローブできます。
  • Wave 5(20ターゲット、4セクター)では、この方法により、15分の手動作業で3件の CRITICAL な CORS、公開された WP ユーザー11件、サブドメイン95件を発見しました。
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 を開きます。プロキシを有効にしてアプリを閲覧します。

  1. アカウントを登録します。
  2. 主なユーザー操作(リソースの作成/読み取り/更新/削除)を行います。
  3. Burp の履歴にあるすべての API 呼び出しを記録します。
  4. 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 のフォールバック
# Preferred: dnsx (concurrent, 50-100x faster at scale)
dnsx -silent -l subs.txt -a -resp-only -o resolved.txt

# Fallback: dig (sequential, only if dnsx binary unavailable)
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 --max-time 30 --connect-timeout 10 -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秒で処理します。同じ処理をデフォルトの50スレッドで httpx に実行させると、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 を参照してください。


検証

  1. 主要な偵察ツール — 必要なツールがインストールされていることを確認します。
    which subfinder httpx nuclei katana 2>/dev/null | wc -l | xargs -I{} echo "{} of 4 core tools found"
    
  2. HTTP プローブ — httpx が動作することを確認します。
    echo "example.com" | httpx -silent -status-code 2>/dev/null && echo "PASS: httpx operational" || echo "NOTE: httpx not installed"
    

すべてのテストで、web2 の偵察準備状況を確認します。


注意点

  • トリアージを伴わない偵察 — どのサブドメインをテストするか優先順位を付けずに 10,000 件のサブドメインを収集しても、それは偵察ではなくデータ収集です。
  • HTTPS を使わない HTTP プローブ — 多くのサービスは HTTPS でしか応答しません。両方のプロトコルをテストしてください。
  • 分析を伴わないスクリーンショット収集 — 自動スクリーンショットは、確認して初めて役立ちます。固有のログインページ、エラーメッセージ、CMS 識別子に価値があります。
  • サービスを識別しないポートスキャン — 開いているポート 8443 は何のサービスか分かりません。バナーを取得して、実際のサービスを特定してください。
  • 古い偵察データ — 30 日以上前のサブドメインデータは、信頼性がますます低くなります。エンゲージメントごとに偵察を更新してください。

関連スキルとチェーン

  • 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 の脆弱性発見へ振り分けます。

コメント