🔌 API Security August 3, 2026 · 14 min read

API Penetration Testing Methodology: A Tester's Playbook

Field-tested API penetration testing methodology — discovery, auth, BOLA, business logic, rate limits, SSRF, GraphQL. Ten phases, real tooling, honest scope.

API
🔌 API Security
API

API penetration testing is treated by many providers as web application penetration testing with a slightly different output format. It is not. Web app pentesting evolved around browser-rendered surfaces with a human user in the loop; API pentesting concerns machine-to-machine interfaces that often have no UI, no rate-limit forgiveness, and authorisation logic that is structurally different from the per-page checks an app does for a logged-in user. The findings shift accordingly — broken object-level authorisation, mass-assignment, rate-limit absence, and business-logic abuse dominate, while the classic injection and XSS findings sit lower in the count. After running API engagements as API penetration testing engagements across many products, a consistent ten-phase methodology produces the densest finding-per-hour ratio. This is that playbook — phase by phase, with the tooling, the techniques, and the failure modes pentesters hit when they skip steps.

Why API pentest methodology differs from web app pentest methodology

The framing difference matters because it changes what gets tested and what gets missed.

Web app pentest assumes a user

A web application penetration test is built around the workflow of a human user clicking through a UI. The tester observes what the browser renders, interacts via Burp, and surfaces vulnerabilities at the points where the UI hands data to the server. Tools like the Burp Suite vs OWASP ZAP ecosystem are optimised for this flow.

API pentest assumes a machine

An API penetration test has no human in the loop. The “client” is another service, a CI pipeline, a mobile app, or a third-party integration. The tester interacts directly with the API surface — without rendered context, without UI-layer input validation hiding broken server logic, and often without the rate-limit forgiveness the web app gives a human. The vulnerability classes that surface most reliably are the ones the UI was hiding: BOLA, mass assignment, broken function-level authorisation, business logic abuse.

What this means for the test plan

Three things change in the methodology:

  1. Discovery dominates Phase 1. Documented endpoints are a fraction of the real surface; undocumented endpoints, internal endpoints, and version-skewed endpoints often hold the most critical findings.
  2. Authorisation testing is the deepest phase. Object-level and function-level authorisation flaws in APIs typically eclipse injection findings by volume.
  3. Business logic and abuse cases get explicit dedicated time. APIs are abused at the logic layer (race conditions, sequence bypass, quota bypass) far more than at the protocol layer.

The methodology below reflects these emphases.

Phase 0 — pre-engagement scoping

Skipped phases produce ambiguous reports. Phase 0 prevents the most common engagement failures.

ItemWhat to confirmWhy it matters
API inventoryList of every API in scope, base URL, version, business ownerAvoids surprise discoveries of out-of-scope APIs during testing
Authentication mechanismOAuth, API key, JWT, mTLS, session cookies, federated identityDetermines test plan for Phase 2
Test accountsTwo or more accounts at every privilege level for authz testingBOLA/BFLA testing is impossible without horizontal accounts
Rate-limit policyThrottle thresholds, IP allow-list for testing, account that gets exemptedAvoids inadvertently triggering customer-impacting throttles
OOB testing allowancePermission for SSRF probes, Collaborator-style callbacksSSRF findings are missed without OOB tooling
Data classificationCategories of data the API serves (PII, PCI, PHI, internal-only)Calibrates report severity language
Production vs stagingWhich environment the test runs against, with explicit risk acceptanceSome findings only reproduce on production scale

A pre-engagement document covering these items is the difference between an engagement that ships findings and one that gets stuck in dispute over scope. The API penetration testing service walks through the pre-engagement checklist used in practice.

Phase 1 — discovery and surface mapping

Discovery is where the highest-value findings live and where most tests are insufficient. The pattern: testers receive an OpenAPI spec, test against that spec, and miss every endpoint that wasn’t documented.

Sources of API surface

  • OpenAPI / Swagger documents: the easy starting point. Often incomplete or out of date.
  • Postman collections: developer-facing collections frequently reveal internal endpoints not in public docs.
  • GraphQL introspection: if introspection is enabled, the entire schema is queryable.
  • Mobile app reverse engineering: APIs called by the mobile app are often a superset of the documented web app API.
  • JavaScript file inspection: SPAs frequently reveal endpoint URLs in their bundled JS.
  • Source code if available: Git history, particularly old commits, often reveals deprecated endpoints still live.
  • Web archive (Wayback Machine): old API documentation pages sometimes reveal endpoints that still work.

Endpoint enumeration

Once the known surface is mapped, enumerate:

# Common API path patterns
ffuf -u https://api.example.com/FUZZ -w api-endpoints.txt -mc 200,401,403

# Versioned endpoints
ffuf -u https://api.example.com/vFUZZ/users -w numbers.txt -mc 200,401,403

# Internal-versus-external endpoint disclosure via verb
for verb in GET POST PUT PATCH DELETE OPTIONS; do
  curl -sX $verb https://api.example.com/admin/users -o /dev/null -w "$verb %{http_code}\n"
done

Look for:

  • Endpoints returning 401/403 (exist, require auth) versus 404 (don’t exist) — the difference reveals hidden surface
  • OPTIONS responses revealing supported methods
  • Old version paths still active (/v1/ after /v2/ was launched)
  • Trailing-slash or query-string variants behaving differently
  • Same endpoint exposed at multiple subdomains (api.example.com, internal-api.example.com)

The discovery output is the input to every subsequent phase. Investing time here pays compounding returns.

Phase 2 — authentication and session testing

Authentication flaws are protocol-level; session flaws are stateful. Both have well-defined test surfaces.

Authentication tests

TestWhat to check
Token forgery via JWT manipulationalg: none, algorithm confusion, kid injection (see OAuth 2.0 misconfigurations)
Token validation across environmentsToken from staging accepted on production (audience claim missing)
API key in URLKeys in query string get logged in browser history, server logs, referrer headers
API key entropySequential or guessable key format
Auth bypass via header injectionX-Forwarded-For, X-Original-URL, X-Rewrite-URL accepted blindly
Auth bypass via method overrideX-HTTP-Method-Override: GET on a POST-only endpoint
Multiple auth mechanismsBoth API key AND JWT accepted — does one bypass restrictions on the other
Anonymous accessUnauthenticated endpoints inside an “authenticated API”
Pre-authenticated endpointsEndpoints accessible with expired tokens; token revocation not enforced

Session tests

TestWhat to check
Session token rotationLogin does not invalidate prior session
Session token formatSequential or guessable session IDs
Concurrent session policySame user logged in multiple times with same token — is this intended
Logout behaviourLogout invalidates server-side session, not just clears client
Inactivity timeoutLong-idle sessions still accepted
Cookie attributesSecure, HttpOnly, SameSite set appropriately

JWT-specific testing uses jwt_tool:

jwt_tool eyJhbGciOiJSUzI1NiI... -T  # tampering interface
jwt_tool eyJhbGciOiJSUzI1NiI... -X a  # alg=none attack
jwt_tool eyJhbGciOiJSUzI1NiI... -X k -kid "../../../etc/passwd"  # kid injection

Phase 3 — authorisation (BOLA, BFLA, scope abuse)

This is the densest finding category in modern API engagements. The 2023 OWASP API Security Top 10 placed BOLA at #1 for a reason.

Broken Object-Level Authorisation (BOLA)

The classic API authorisation bug: the API receives an object ID and returns data without checking whether the authenticated user is permitted to access that object.

Test methodology:

  1. As User A, perform a normal action — e.g., retrieve “your” order: GET /orders/12345.
  2. Note the object ID format (numeric, UUID, base64-encoded, opaque token).
  3. Substitute another known object ID — User B’s order ID, if you have it from the second test account.
  4. Submit the modified request.
  5. Expect 403. Observe whether you actually get 200.

Variations that catch teams who think they’ve handled the basic case:

  • IDOR in URL path (/orders/12345)
  • IDOR in request body ({"order_id": 12345})
  • IDOR in query string (/orders?id=12345)
  • IDOR in headers (X-User-Id: 12345)
  • IDOR in nested objects (/users/me/orders/12345 — does the API check both ownership of me and ownership of the order?)
  • IDOR via batched requests (/orders?ids=12345,12346 — does the API check each ID individually)
  • IDOR via aliased fields ({"orderId": 12345} vs {"order-id": 12345} — both accepted, only one checked)

Broken Function-Level Authorisation (BFLA)

Similar to BOLA but at the function rather than the object level. The classic test: as a low-privilege user, can you call admin endpoints?

Test methodology:

  1. Log in as admin. Capture the request sequence for admin functions.
  2. Log out, log in as a regular user.
  3. Replay the admin request sequence with the regular user’s auth token.
  4. Expect 403. Observe whether you actually get 200.

Variations:

  • HTTP method bypass: GET /api/admin/users returns 403 but POST /api/admin/users accepts a non-admin token
  • Path traversal in role check: /admin/../users bypasses the admin filter
  • Sibling endpoints with different access policies: /users/12345 (own) vs /users/12346 (other) vs /admin/users/12346

OAuth scope abuse

If the API uses OAuth, test scope enforcement at the API layer (not just at the OAuth server). A token with read:profile should not be able to call write endpoints — but APIs often accept any authenticated token regardless of scope.

Phase 4 — input validation and injection

Injection findings are lower-frequency in modern APIs than in legacy web apps, but they still surface. The categories worth dedicated coverage:

CategoryTest patterns
SQL injection', ' OR '1'='1, time-based payloads, ORM-aware payloads
NoSQL injection{"$ne": null}, {"$gt": ""}, JavaScript injection in MongoDB
Command injection; ls, | ls, $(ls), backticks
LDAP injection*, *)(uid=*, `*)(
XPath injection' or '1'='1, ' or count(/)>1 or '
Server-side template injection (SSTI){{7*7}}, ${7*7}, #{7*7} based on template engine
XML / XXEExternal entity injection if the API accepts XML
Header injectionCRLF injection in user-controlled response headers

The reality of API injection testing in 2026: most modern frameworks parameterise queries by default. The findings are in places where the framework was bypassed — raw query construction, ORM where clauses with string concatenation, dynamic table/column name interpolation, or older code paths that predate the framework’s safe default.

Phase 5 — business logic abuse

Business logic flaws are where the highest-impact API findings live. They are not catchable by scanners. They require the tester to understand what the API is supposed to do and then test what happens when the contract is broken.

Patterns that surface in production audits

  • Quota bypass: free-tier user creates multiple sub-accounts to multiply free quota
  • Sequence bypass: skipping a validation step in a multi-step flow (e.g., creating an order without going through the payment step)
  • Race conditions: applying a coupon code, then applying it again before the first application’s “consumed” state is committed
  • Time-of-check to time-of-use (TOCTOU): passing a check at request validation time, then doing the action after a state change that should have failed the check
  • Negative-quantity abuse: requesting -5 items at $50 each yielding a $250 credit
  • Discount stacking: combining discounts that the business rules say cannot be combined
  • Workflow short-circuit: jumping from step 1 to step 5 in an approval flow without intermediate sign-offs
  • State manipulation: setting order_status = "paid" directly via API, when the intended path is via the payment webhook

The methodology for this phase is more interview-driven than tool-driven. Ask the business owner: what would be expensive if it happened? Then design specific test cases.

Phase 6 — mass assignment and property abuse

Mass assignment occurs when an API accepts a JSON object and persists all the fields, including ones the user should not control.

Test methodology

  1. Make a legitimate request, e.g. PATCH /users/me with {"name": "New Name"}.
  2. Observe what fields the user object has (from a corresponding GET /users/me).
  3. Resubmit the PATCH with additional fields: {"name": "New Name", "is_admin": true, "balance": 999999, "email_verified": true}.
  4. Re-fetch the object and observe which extra fields were accepted.

Production findings typically include:

  • is_admin or role field updatable via user-profile PATCH
  • created_at, updated_at, id updatable (data integrity issue, not always security)
  • email_verified toggleable to true without verification flow
  • Currency, balance, or quota fields directly mutable
  • Foreign-key fields (like account_id) changeable, enabling pivot to another tenant

The fix is server-side allow-listing: explicitly enumerate which fields the endpoint accepts, reject the rest. Deny-listing fields is a common but fragile fix.

Phase 7 — rate limit and resource consumption testing

Rate limit absence is the single most common API finding by sheer frequency.

Test methodology

TestHow to check
Unauthenticated rate limitSend 1000 requests to a public endpoint in 10 seconds. Did the API throttle?
Per-user rate limitAuthenticated requests: send 1000 in 10 seconds as one user. Did the API throttle?
Per-IP rate limitSame test, IP basis (matters for unauthenticated endpoints)
Distributed rate limitSend from multiple IPs. Did the throttle still trigger?
Resource-intensive endpointSubmit a query that does expensive work (large list, full-text search, report generation). Does it cap, or does it eat CPU?
Pagination abuseRequest ?per_page=10000000 — does the API cap or attempt to serve?

The findings often surprise development teams: they assumed CloudFront, the load balancer, or the framework was handling rate limiting. None of those tend to handle authenticated per-user rate limiting unless explicitly configured.

Phase 8 — SSRF and out-of-band

Server-Side Request Forgery is one of the highest-impact findings to surface in API testing because it often chains to cloud credential theft.

Test methodology

  1. Identify any endpoint that takes a URL or hostname as input. Common patterns: webhook configuration, file upload by URL, image processing by URL, integration test endpoints.
  2. Submit a URL pointing at an out-of-band server (Burp Collaborator, interactsh, your own controlled host) and watch for callbacks.
  3. If callbacks arrive, escalate: try cloud metadata endpoints (http://169.254.169.254/latest/meta-data/), internal services, port scanning the internal network.

The cloud metadata endpoint is the highest-impact SSRF target. If the SSRF can reach it, and the application is hosted on a cloud instance with IMDSv1 enabled or with a heavily-privileged IAM role, the SSRF yields cloud credentials. This is documented in detail in our container security audit checklist (check #47 — metadata endpoint blocking).

# Common SSRF payloads
http://169.254.169.254/latest/meta-data/  # AWS IMDS
http://metadata.google.internal/  # GCP
http://169.254.169.254/metadata/instance  # Azure (requires header)
http://localhost:9200/  # Elasticsearch
http://localhost:6379/  # Redis
http://localhost:8500/v1/agent/services  # Consul

Phase 9 — GraphQL-specific testing

GraphQL APIs have a different attack surface from REST. The testing methodology shifts.

Introspection abuse

If introspection is enabled in production, the entire schema is queryable:

{
  __schema {
    types {
      name
      fields { name type { name } }
    }
  }
}

Production GraphQL APIs should disable introspection unless there’s a specific reason to keep it on.

Query depth and complexity attacks

Without query depth limits, nested queries can produce expensive operations:

{
  user(id: 1) {
    friends { friends { friends { friends { friends { id } } } } }
  }
}

Five levels of nesting on a query that touches a friend-of-friend graph can cause memory exhaustion. Test by submitting increasing depth and observing CPU/response time.

Batching attacks

GraphQL supports aliasing, which enables a single request to perform many operations:

{
  attempt1: login(username: "admin", password: "password1") { token }
  attempt2: login(username: "admin", password: "password2") { token }
  attempt3: login(username: "admin", password: "password3") { token }
}

If the API rate-limits per HTTP request but not per GraphQL operation, this bypasses the rate limit. Test by aliasing the same operation multiple times and observing throttle behaviour.

Field-level authorisation

GraphQL field resolvers run independently. Authorisation must be enforced at the field level, not just at the query level. A query returning user { id name email phone ssn } requires authorisation on every field, not just the user object.

Phase 10 — reporting and re-test

The finding list is half the deliverable. The other half is the report.

Findings structure

For each finding, the report should answer:

  • Title and severity (CVSS 3.1 score with justification)
  • The attack chain narratively (what the attacker does, in plain language)
  • Reproduction steps with exact requests and responses
  • Affected endpoints, parameters, and accounts used
  • Recommended fix with specific implementation guidance
  • Re-test plan once the fix is shipped

Severity calibration

API findings often get under-rated because the tester treated the finding in isolation. The right calibration considers chained impact:

Finding typeStandalone severityChained severity
BOLA on order endpointHigh (PII access)Critical (if chained with mass assignment to take over orders)
SSRF to internal endpointMediumCritical (if reaches cloud metadata)
Missing rate limit on loginMediumHigh (enables credential stuffing at scale)
Mass assignment on profileMediumCritical (if is_admin is among the accepted fields)
OAuth scope not validatedMediumHigh (if combined with a token leak)

Report the chained severity when the chain is achievable in the same engagement.

Re-test

The re-test is where engagements often go wrong. Patches that look fine in code review can fail in implementation. Always re-test by attempting the original exploit, then test variations to confirm the fix is structural rather than addressing only the specific payload.

The honest tester’s playbook

The ten-phase methodology produces a high finding-density engagement. The compressed playbook for testers who have done this often enough that the phases are muscle memory:

  1. Map the surface beyond what’s documented. Every undocumented endpoint is a finding waiting.
  2. Get two accounts at every privilege level. BOLA testing without horizontal accounts is fiction.
  3. Authorisation is half the engagement. Spend the time.
  4. Business logic is where the seven-figure findings live. Interview the business owner.
  5. Mass assignment is the easiest critical finding to surface in modern APIs. Test it on every PATCH.
  6. Rate limits are nearly universally missing on at least one critical endpoint. Test the worst-case endpoint first.
  7. SSRF that reaches cloud metadata is one of the highest-impact findings in the API space. Always check.
  8. GraphQL has its own attack surface. REST tooling doesn’t cover it.
  9. Report chained severity, not standalone severity. The customer pays for risk reduction, not finding count.
  10. Re-test what you found. Implementations regress.

For broader context on where this fits in the testing lifecycle, see our web application pentest methodology and SaaS API security testing guide. Teams pairing this work with source code security review and continuous testing typically converge on a quarterly cadence — every release in scope, every quarter retested.

The argument was never whether APIs need pentesting. Every API does. The argument is whether the testing methodology covers the categories where the real findings live, or whether it follows a scanner’s report through the easier categories and stops there. The phases above are the difference between the two.

#API Security #Penetration Testing #BOLA #GraphQL #AppSec

Related articles

Need expert help with API Security?

Our certified security team is ready to assess your environment and recommend the right solutions.

Book a Free Consultation