Skip to main content

Pentrova is launching soon. Join the waitlist for early access.Join the waitlist

Research

Sample

Authorization Matrix walkthrough: finding BOLA in a real API

A step-by-step walkthrough of how the Authorization Matrix models roles, captures reference responses, and flags cross-tenant BOLA leaks.

Broken object-level authorization hides in the traffic between two roles, not inside a single session. The Authorization Matrix is the Pentrova capability built specifically to surface that class of bug. This walkthrough takes a realistic multi-tenant API and shows the three things the matrix does that a traditional scanner cannot — with the request/response evidence at each step.

If you want the conceptual background first, BOLA hunting in microservices covers why this class is so easy to miss. This post is the hands-on tour.

The target: a multi-tenant SaaS API#

Picture a typical B2B SaaS API with three roles:

  • tenant-admin — full access within their own tenant
  • tenant-member — scoped access within the same tenant
  • stranger — a valid user belonging to a different tenant

Broken access control is the most prevalent risk in the OWASP Top 10, and this three-role shape is enough to surface most of it.

Step one: establish every role#

Before any testing starts, the matrix establishes a persistent session for every role the target exposes. The pattern generalises to multi-tenant SaaS, partner portals, and internal admin surfaces that share infrastructure with customer APIs. The matrix stores cookies, bearer tokens, certificates, and any refresh grants each role needs, so every subsequent request is correctly authenticated and tokens never expire mid-run.

This is also where API Pentesting wires in the six supported auth modes — bearer, API key, basic, , custom (HMAC / SigV4), and — so the sessions mirror what production actually enforces.

Step two: capture reference responses#

With every role established, Pentrova walks the protected endpoints under one role — typically the highest-privilege role with legitimate access — and captures the reference response for each one. The reference response is the ground truth: this is what the endpoint returns when the caller is authorised.

# Captured under tenant-admin — the authorised baseline
GET /api/v2/projects/5521/members → 200
[ { "id": 88, "email": "lead@acme.example", "role": "admin" },  ]

Step three: replay under every other role#

The same request is now replayed under every other role. The response is diffed against the reference with a normalisation pass that ignores headers and timestamps. What matters is whether the response leaks any of the same data.

# Replayed under stranger (different tenant) — expected 403
GET /api/v2/projects/5521/members → 200
[ { "id": 88, "email": "lead@acme.example", "role": "admin" },  ]
#   ^ cross-tenant member list disclosed → BOLA finding

If role B sees data only role A should have seen, the matrix publishes a finding with the request, both responses, and the specific fields that leaked. Because the result is reproduced against the live target, it arrives as deterministic proof, not a probability score.

Where the interesting bugs hide#

List endpoints and aggregate dashboards are the usual suspects:

  • List endpoints that forget to scope by tenant return every object the database can reach when an admin issues the request — and the member or stranger replaying it gets the full list too.
  • Aggregate dashboards are the same pattern at a higher level: the sums and counts leak the underlying cross-tenant visibility even when the individual records appear filtered.
  • Nested resources like /projects/{id}/members often inherit the parent’s authorization check incompletely, scoping the project but not the members beneath it.

Reading the finding#

A matrix finding is designed to be fix-ready. It names the endpoint, the two roles involved, the reference and replayed responses, and the exact fields that leaked. For the example above, the fix is an object-ownership check on projects/{id} that also scopes the nested members collection to the caller’s tenant.

Key takeaways#

  • The matrix does not guess what the bug looks like — it reasons about the relationship between roles.
  • Three roles (admin, member, cross-tenant stranger) surface most broken-access-control issues; add tenants for multi-tenant platforms.
  • Reference-then-replay produces a deterministic diff, so the finding is evidence rather than a maybe.
  • List, aggregate, and nested-resource endpoints are where cross-tenant leaks concentrate.

FAQ#

How many roles can the Authorization Matrix test? As many as your application models. Most teams start with four to six (owner, admin, member, viewer, external, unauthenticated) and add tenants for multi-tenant platforms.

Does the matrix test BFLA (broken function-level authorization) too? Yes. Replaying privileged functions under lower-privileged roles surfaces broken function-level authorization alongside object-level leaks.

What makes this different from a normal access-control scan? A normal scan operates in one session and cannot see cross-role leaks. The matrix captures a per-role reference and diffs every cross-role replay against it, which is the only reliable way to detect the relational failure that defines .

See the Authorization Matrix in the platform pipeline, or run it against your own API.

Updated

Written by

Pentrova Research Pentrova Research

Pentrova Research writes about deterministic offensive-security proof, LLM-driven pentest chains, and how to ship exploit-grade evidence into engineering pipelines.

Keep reading

Site search

↑↓ navigateEnter openEsc close