How I Run an API Penetration Test
APIs move the vulnerability surface away from the browser and into object references, token handling and business rules. This is how I test one, and the findings box shows the pattern of what an API assessment typically surfaces.
1. Get the contract and every auth role
I want the OpenAPI/Swagger or GraphQL schema, and at least two accounts per role (two low-priv users, an admin, an unauthenticated baseline). Testing authorization needs a second identity to pivot against.
2. Enumerate and map
Build the full endpoint + parameter inventory before attacking it.
- Import the spec into Burp/Postman; fill gaps with Kiterunner and ffuf against common route wordlists
- GraphQL: attempt introspection, then map types, queries, mutations and nested resolvers
- Note every object identifier in every path and body — these are the BOLA candidates
3. Authorization first (BOLA / BFLA)
The OWASP API Top 10 leads with broken object-level and function-level authorization for a reason. With user A's session I request user B's objects by ID, call admin-only functions, and swap tenant identifiers. Autorize automates the replay-and-compare.
4. Tokens, mass assignment, injection
JWT handling (alg:none, weak secret, missing audience/expiry checks), object properties the client shouldn't be able to set (role, is_admin, price), and the classic injection set against any parameter that reaches a query or a shell.
5. Business logic and rate limiting
Replay purchases at negative quantity, skip workflow steps, brute-force OTPs with no lockout, race the coupon-redemption endpoint. These never show up in a scanner and are often the highest-impact findings.
What this kind of project turns up
Representative findings from real engagements. Details are altered and unlinked from any client — the pattern and severity are what matter.
Any authenticated user could read and modify any order by incrementing the ID — PII, addresses and totals exposed across tenants. CWE-639.
Forged an admin token by stripping the signature and setting `alg` to `none`. Full function-level auth bypass.
Adding `"role":"admin"` to the profile-update body was honoured server-side. Privilege escalation from a self-registered account.
6-digit code brute-forceable in minutes; no lockout, no exponential backoff.
Full schema disclosure including internal admin mutations. Low impact alone, but it hands an attacker the map.
Leaked ORM details and column names. Fixed with a sanitized error middleware.
Tools mentioned
Test APIs identity-first: two accounts, every object reference, every privileged function. Injection still matters, but broken authorization and business-logic flaws are where API assessments actually pay off.