Skip to main content

Service

API Penetration Testing

Authorisation, object-level access and abuse testing against your API surface.

The top entry in the OWASP API Security Top 10 is broken object level authorisation, and it stays there because no scanner can find it. Every request is valid, every response is a 200, and the only thing wrong is that the object belonged to somebody else. Finding that requires two accounts and a person who knows what the objects are supposed to mean.

How this works

Inventory before testing

The specification is the starting point and not the boundary. Route tables, client bundles, mobile applications and access logs consistently reveal endpoints the documentation does not have, and those are the ones most likely to predate the current authorisation model. Testing a documented surface reproduces the client's own blind spot.

Two accounts per role, then replay

Every object identifier seen as user A is requested as user B. Anything other than a refusal is a finding. The same replay runs unauthenticated, because an endpoint that never required a token at all is a category of failure that has cost organisations millions of records and takes minutes to check.

Verbs, fields and mass assignment

Each route is tested with every verb it might accept, since read access is commonly checked and delete is not. Responses are compared against what the interface displays to find fields that should never have left the server. Write requests are tested with added fields such as role, tenant or balance to see which the server accepts.

Abuse rather than only access

Rate limits are tested for whether they hold under concurrency rather than sequence, since anything protected by a per-request counter can be defeated by arriving in parallel. Where GraphQL is in use, aliasing and batching are tested specifically, because both multiply work inside a single request that a per-request limiter counts once.

What we look for

  • Object-level authorisation: whether ownership is checked, or only authentication
  • Function-level authorisation: verbs and administrative routes reachable by ordinary accounts
  • Property-level exposure: tokens, hashes, internal scores and personal data in responses the interface never renders
  • Mass assignment on write endpoints
  • Undocumented, versioned and forgotten endpoints, including the ones no current client calls
  • Rate limits that fail under concurrent rather than sequential requests
  • GraphQL alias and batch multiplication, and introspection left enabled in production
  • Token handling: algorithm confusion, unchecked audience and issuer claims, and expiry that is not enforced

What you get

  • An endpoint inventory built from your systems rather than from your documentation
  • Every finding with the exact request and response that proves it
  • Authorisation results per role pair, so the gaps are visible as a matrix rather than a list
  • Remediation aimed at the data layer, since a per-controller fix is one a future endpoint will miss

What this does not include

  • Load testing, though rate limiting is tested for correctness
  • Testing third-party APIs you do not own without their written authorisation
  • Fixing the implementation, though the report is specific about the change

Questions people ask

Do you need our OpenAPI specification?
It helps and it is not sufficient. The specification describes what was documented; the testing also covers what is deployed, which is regularly a superset. Where no specification exists the inventory is built from the clients and the routing layer instead.
How many test accounts?
Two per role at minimum, plus one privileged account and an unauthenticated position. One account per role makes object-level authorisation untestable, which is the same as not testing the top API risk at all.
REST and GraphQL?
Both. GraphQL moves authorisation from the route to the resolver, which multiplies the number of places it can be forgotten, and adds alias and batch abuse that REST does not have. Those get specific attention rather than the REST methodology applied unchanged.