mcpField
H
hunt-schema-enumeration

hunt-schema-enumeration

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

hunt-schema-enumeration について

API のセキュリティテスト担当者向けのブラックボックス型スキーマ列挙スキルです。構造化エラーやクエリ応答からテーブル名、フィールド名、エンドポイントを探り、PostgREST、入力検証エラー、GraphQL の確認方法と限界を説明します。

主な機能

  1. 01PostgREST のヒントからテーブル名を発見
  2. 02入力検証エラーからフィールド情報を抽出
  3. 03GraphQL のイントロスペクションクエリ
  4. 04ワードリストによるテーブル名のファジング
  5. 05結果の確認と誤検知の判別

活用シーン

  1. 01PostgREST API が公開するテーブルの把握
  2. 02エンドポイントのエラーから必須フィールドを確認
  3. 03イントロスペクション制限時に GraphQL の型情報を調査
  4. 04許可された書き込みテストの対象エンドポイントを特定

インストール

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

$npx skills add https://github.com/uphiago/recon-skills --skill hunt-schema-enumeration

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

詳細

使用するタイミング

対象の API は、有効なテーブル名、フィールド名、エンドポイントパスの手がかりとなる構造化エラーメッセージ(JSON)を返します。これは REST/GraphQL API に対するブラックボックス調査で最も成果の高い手法です。ファジングリクエストを 1 回送るだけで、データベーススキーマ全体が明らかになります。

特によく見られるのは、PostgREST(Supabase)、FastAPI(.NET)、Zod(Next.js/Node)、tRPC、GraphQL、および検証エラーの詳細を本番環境で有効にしているあらゆるフレームワークです。


フェーズ 1 — PostgREST エラーヒントの列挙

PostgREST は Supabase/PostgreSQL 用の REST API レイヤーです。存在しないテーブルをクエリすると、実際のテーブル名を含むヒントが返されます。

SUPABASE_URL="https://PROJECT.supabase.co"
ANON_KEY="eyJ..."

# Fuzz with common table names — read the hints
for table in users profiles posts products orders data config settings; do
  echo "=== $table ==="
  curl --max-time 30 --connect-timeout 10 -sk "${SUPABASE_URL}/rest/v1/${table}?select=*&limit=1" \
    -H "apikey: ${ANON_KEY}" \
    -H "Authorization: Bearer ${ANON_KEY}" 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
hint=d.get('hint','')
if hint: print(f'  -> {hint}')
"
done

# The response pattern:
# {"hint":"Perhaps you meant the table 'public.real_table_name'"}
# {"hint":"Perhaps you meant the table 'public.user_sessions'"}

標的型ファジング用のワードリストを作成する:

# Common patterns found in field:
# - Game apps: hands, scores, sessions, players, items, inventory
# - SaaS: subscriptions, subscribers, billing, invoices, teams, api_keys  
# - Health: patients, appointments, assessments, prescriptions
# - Gov: citizens, certificates, documents, protocols
# - Finance: transactions, accounts, wallets, withdrawals, deposits

フェーズ 2 — Zod/FastAPI の検証エラーの調査

最新のフレームワークは、想定されるすべてのフィールドを明らかにする詳細な検証エラーを返します。

FastAPI(.NET/Go)
# POST with empty body or wrong fields
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://api.target.com/endpoint" \
  -H "Content-Type: application/json" -d '{}' 2>/dev/null
# Response reveals ALL required fields:
# {"errors":{"usuario":["required"],"senha":["required"]}}
Zod(Next.js/Node)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/workspaces" \
  -H "Content-Type: application/json" -d '{}' 2>/dev/null
# Response: {"error":{"name":"ZodError","message":"[\n  {\"expected\":\"string\",\"path\":[\"name\"]}\n]"}}

フェーズ 3 — GraphQL イントロスペクション

# Standard introspection query
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/graphql" \
  -H "Content-Type: application/json" \
  -d '{"query":"{__schema{types{name fields{name type{name}}}}}"}' 2>/dev/null

# Even if introspection is disabled, error messages reveal type names:
# "Cannot query field 'x' on type 'User'. Did you mean 'users'?"

フェーズ 4 — 積極的なテーブルファジング

以下を組み合わせて包括的なワードリストを生成します:

# 1. From JS bundle analysis
grep -Eo 'from\(["\x60][a-zA-Z_]+["\x60]\)' /tmp/target.js | sort -u

# 2. From common patterns
# Singular/plural: user/users, post/posts, product/products
# Snake/camel: user_sessions, userSessions, UserSessions
# Domain-specific: appointments, patients, assessments, certificates

# 3. Systematic fuzz
for table in $(cat /tmp/wordlist.txt); do
  curl --max-time 30 --connect-timeout 10 -sk -w "%{http_code}" "${BASE}/rest/v1/${table}?select=count" \
    -H "apikey: ${KEY}" 2>/dev/null | tee -a /tmp/fuzz_results.txt
done

検証

  • PostgREST のヒットを確認:レスポンスが [](空の配列 = テーブルは存在するが、RLS によって読み取りがブロックされている)またはデータが返される
  • Zod のヒットを確認:エラーに、想定される正確なフィールド名と型が列挙されている
  • FastAPI のヒットを確認:detail 配列に不足しているフィールドが列挙された 422
  • 誤検出:一般的な 404 HTML ページ(JSON エラーではない)

次にすること

  • PostgREST のヒントでテーブルが明らかになった場合 → hunt-write-gap に進む(PATCH/POST/DELETE をテスト)
  • Zod のエラーでフィールドが明らかになった場合 → hunt-business-logic をテストする(マスアサインメント、価格の改ざん)
  • FastAPI で認証スキーマが明らかになった場合 → jwt-attack または api-noauth-hunt をテストする
  • スキーマの列挙は常に次の攻撃につながります。最終ステップではありません

検証

このセルフテストを実行し、スキーマ列挙調査の準備が整っていることを確認します:

  1. スキルの整合性 — スキルファイルが読み取り可能で、形式が正しいことを確認します:

    grep -q "name: hunt-schema-enumeration" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL"
    grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL"
    
  2. カテゴリの確認 — スキルにカテゴリがあることを確認します:

    grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL"
    
  3. 落とし穴のセクション — 落とし穴が記載されていることを確認します:

    grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
    

3 つのテストすべてにより、スキルが適切に構成され、使用する準備が整っていることを確認できます。


落とし穴

  • 機密フィールドを伴わないスキーマ列挙 — API スキーマを把握することは調査です。悪用可能なフィールドや変更操作を実証する必要があります。
  • イントロスペクションによる GraphQL スキーマの取得 — イントロスペクションは機能であり、バグではありません(本番環境で明示的に無効化されている場合を除く)。
  • エラーメッセージによるデータベーススキーマの開示 — テーブル名が明らかになる SQL エラーは情報開示であり、スキーマ固有の問題ではありません。開示された内容に基づいて評価します。
  • OpenAPI 仕様が一般公開されている — /swagger.json または /openapi.json は、API 利用者向けに意図的に公開されています。公開されている管理用/内部エンドポイントに基づいて評価します。

コメント