August 31, 2026
A Senior Pentesterβ Approach to IDOR and Authorization Testing
When I see an id parameter during an application security assessment, I don't immediately start changing 100 to 101.
By clipper
3 min read
That is usually the first thing a beginner does.
My first question is different:
"What does this ID actually represent, and who is supposed to have access to that object?"
For example, I might find a request like:
GET /api/orders?id=12345GET /api/orders?id=12345At first glance, it looks like a simple IDOR candidate. But an experienced tester knows that the number itself is not the vulnerability.
The real question is whether the application verifies that the authenticated user is authorized to access order 12345.
So I first use the application normally.
I create an order with my test account and observe the requests generated by the application. I record the object identifier, where it appears, and which other endpoints use the same object.
Then I switch to a second authorized test account.
Now I have something much more valuable than a random number.
I have an authorisation boundary.
Account A owns Object A.
Account B owns Object B.
I then ask the application a simple question:
"What happens if Account B requests Account A's object?"
If the server correctly rejects the request, the authorization control appears to be working for that endpoint.
If the server returns Account A's private information, I have demonstrated a broken object-level authorization issue.
But I don't stop there.
A real application rarely has only one operation for an object.
If I find an order, I look for everything connected to that order:
View
Download
Update
Delete
Export
Share
Cancel
ApproveView
Download
Update
Delete
Export
Share
Cancel
ApproveThe interesting part is that authorization is sometimes implemented inconsistently.
For example:
GET /api/orders/12345
β 403 Forbidden
GET /api/orders/12345/invoice
β 200 OKGET /api/orders/12345
β 403 Forbidden
GET /api/orders/12345/invoice
β 200 OKThat immediately makes me investigate the relationship between those endpoints.
The application may have protected the main object but forgotten to protect a secondary endpoint.
This is why I don't think of IDOR as an id parameter vulnerability.
I think of it as an authorization-model problem.
I Also Stop Thinking Only About Users
Suppose the application is a SaaS platform.
Now the structure might look like this:
Organization A
βββ User A
βββ Projects
βββ Orders
βββ Documents
Organization B
βββ User B
βββ Projects
βββ Orders
βββ DocumentsOrganization A
βββ User A
βββ Projects
βββ Orders
βββ Documents
Organization B
βββ User B
βββ Projects
βββ Orders
βββ DocumentsAt this point, my question changes again.
I'm no longer asking:
"Can User A access User Bs object?"
I'm asking:
"Can anything belonging to Organization A cross into Organization B?"
A cross-tenant authorization failure can be considerably more serious because the boundary is no longer simply between two users.
It is between customers or organizations.
Then I Look at the Object Relationships
Modern applications rarely operate on isolated objects.
A request might contain:
{
"organization_id": 10,
"project_id": 250,
"document_id": 731
}{
"organization_id": 10,
"project_id": 250,
"document_id": 731
}I don't automatically assume these three IDs belong together.
I want to understand the relationship:
User
β
Organization
β
Project
β
DocumentUser
β
Organization
β
Project
β
DocumentThe server should establish that relationship itself.
If the application checks only one of those relationships and blindly trusts the others, there may be an authorization weakness.
This is where IDOR testing becomes much more interesting.
I Don't Ignore UUIDs
Another common mistake is assuming:
"It's a UUID, so IDOR isn't possible."
That's wrong.
A UUID can make enumeration difficult, but it does not replace authorization.
If I legitimately obtain:
550e8400-e29b-41d4-a716-446655440000550e8400-e29b-41d4-a716-446655440000and another user can use that identifier to access the object without authorization, the application still has an authorization problem.
The question is never:
"Can I guess the ID?"
The question is:
"If I have an object reference, does the server verify that I am allowed to use it?"
I Also Think About State
Objects change over time.
An application might have:
Created
β
Pending
β
Approved
β
Completed
β
ArchivedCreated
β
Pending
β
Approved
β
Completed
β
ArchivedAuthorization shouldn't accidentally disappear when the object's state changes.
For example, a document might belong to User A initially.
Later it gets transferred to User B.
I want to know whether User A still has access through an old endpoint, download URL, cached reference, or secondary API.
This is no longer just basic ID manipulation.
It is understanding the application's authorization state machine.
The Most Important Thing I Look For
Eventually, my thinking comes down to four questions:
Who am I?
What object am I trying to access?
Who owns that object?
What server-side rule says I am allowed to access it?
If the application cannot correctly answer the fourth question, changing an ID may expose something much bigger than a single record.
It could expose:
- Another user's personal information
- Private documents
- Financial information
- Internal company data
- Administrative resources
- Cross-tenant information
- Or functionality that allows unauthorized modification
And that is where severity comes from.
Not from the fact that an ID changed.
The Difference in Thinking
A beginner sees:
id=100id=100and thinks:
"What happens if I change it to 101?"
An experienced tester sees:
id=100id=100and thinks:
"What object is 100?"
Then:
"Who owns it?"
Then:
"How does the server determine ownership?"
Then:
"Where else is this object referenced?"
Then:
"What other operations can I perform on it?"
Then:
"Does the same authorization rule exist across every endpoint?"
Then:
"Can this cross a user, role, organization, or tenant boundary?"
That change in thinking is the real progression from basic IDOR testing to senior-level authorization testing.
The goal isn't to change more IDs.
The goal is to understand the application's trust model and find where that model breaks.