Skip to main content

Case study

Finding the authorisation gaps before launch, not after

A platform preparing to launch asked for a web, API and cloud assessment. The interesting findings were not missing patches but authorisation decisions the application made correctly in the interface and incorrectly in the API behind it.

Illustrative. Engagement reports are confidential. No client, system, date or figure here is real. This is a composite showing the shape of the work and the class of finding.

At a glance

Engagement
Pre-launch assessment: web application, API and cloud
Timeframe
Before launch, with a retest after the fixes
Scope
The application, the API behind it, and the cloud identity it runs under
Outcome
Fixed and verified by retest before launch, with residual risks accepted knowingly

The situation

A team was weeks from opening a platform to real users. The application had been built quickly, reviewed internally, and scanned with the usual tooling, which had come back close to clean. The question they asked was the right one: not "are we vulnerable" but "what would someone who actually tried get to?"

The approach

  • Mapped the roles the product intends to have, then tested each boundary from the account below it rather than from an administrator's view
  • Worked against the API directly instead of only through the interface, because the interface hides endpoints and enforces rules the server may not
  • Reviewed cloud identity by following privilege paths from a hypothetical initial foothold, rather than linting policy documents in isolation
  • Retested every finding after remediation rather than accepting a code change as proof

What turned up

Authorisation enforced in the interface, not the server

Several actions were hidden from users who should not perform them, but the endpoints behind those actions accepted the request from any authenticated session. A scanner cannot find this: every response is a valid 200, and only knowing what the roles are supposed to mean makes it a finding.

Object-level access checks keyed on the wrong thing

Endpoints confirmed the caller was logged in and that the record existed, but not that the record belonged to the caller. This is the most common serious API finding in practice and it is almost always invisible from the front end.

Cloud roles broader than the workloads needed

Individually defensible permissions combined into a path from a low-value workload to data that workload had no reason to reach. Reported as the path an attacker walks, not as a list of policy diffs.

What changed

Findings were fixed before launch and each fix was verified by retest rather than accepted on trust. The team went live knowing which failure classes had been closed and which residual risks they had consciously accepted.

The lesson

Automated scanning is good at known-bad and blind to "working exactly as written, and wrong." Authorisation is a business-logic question: it needs someone who knows what the roles are meant to mean, testing the server rather than the screen.

What to check in your own environment

  • For every action your interface hides from a role, call the endpoint behind it directly from an account in that role
  • For every endpoint that takes a record identifier, ask for a record that belongs to another account
  • Write down what each role is meant to be able to do, so a test has something to fail against
  • Start from your lowest-value workload and follow its permissions to see what data they can reach
  • Count a fix as done when it has been retested, not when the code has changed

Recognise your own systems in this?

A short conversation is the quickest way to find out whether the same thing is true of yours, and what it would take to check.