IDOR Attacks: Why Trusting IDs Is a Costly Mistake

So… what exactly is IDOR?

An Insecure Direct Object Reference (IDOR) is a security flaw where an application lets a user access data simply by providing an internal identifier (like an ID number), without checking whether that user is actually allowed to access it.

In simple terms:

  • The application accepts an ID from the user
  • It fetches the data linked to that ID
  • But it fails to verify ownership or permission

If a user can change an ID in a request and see or modify someone else’s data, the application has an IDOR vulnerability.

At its core, IDOR is an authorization failure, not an authentication problem.
The user may be properly logged in — the app just doesn’t check what they’re allowed to access.


A simple story that explains IDOR perfectly

Imagine a hotel where:

  • Each room has a number
  • The receptionist only asks for the room number
  • They never ask for your name or room key

If you say:

“I want room 305”

They give you the key — even if it’s not your room.

That’s exactly how IDOR works in software.


How IDOR looks in the real world (step by step)

Normal user behavior

Alice logs into an online shop and views her invoice:

GET https://shop.example.com/invoices/1234

The server sends invoice 1234 back to Alice.

So far, everything looks fine.


What the attacker does

Bob logs into his own account and changes the number:

GET https://shop.example.com/invoices/1235

If the server sends back invoice 1235 without checking who owns it, Bob now sees someone else’s invoice.

That single missing ownership check is IDOR.


IDOR in APIs (very common)

APIs are especially vulnerable because everything is parameter-based.

Normal API request

GET /api/users/123/profile
Authorization: Bearer <token-for-user-123>

Attacker changes the ID

GET /api/users/124/profile

If the server responds with user 124’s profile, the API is vulnerable.

The token proves the attacker is logged in —
but the server never verifies which user that token is allowed to access.


The different ways IDOR shows up

Horizontal IDOR

Accessing data belonging to another user at the same level

Example:

  • User A views User B’s order
  • Both are normal users

Vertical IDOR

Accessing data belonging to a higher-privileged role

Example:

  • Regular user accesses admin resources
  • Customer accesses internal employee data

Vertical IDOR is usually more severe.


Where IDOR can exist

IDOR can appear anywhere a user controls an identifier, including:

  • URLs
  • Query parameters
  • JSON request bodies
  • Form fields
  • Cookies
  • Headers
  • Mobile app API calls

If the user can influence an object reference, IDOR is possible.


Why IDOR happens (the real reasons)

IDOR usually happens because of assumptions, not bad intentions.

Common causes:

  • Authorization is checked in the UI but not on the server
  • Developers assume users won’t change IDs
  • The app checks login status but not ownership
  • Sequential or predictable IDs are used
  • Authorization logic is scattered across the codebase
  • Internal APIs are trusted too much

In short: authentication exists, authorization is incomplete or missing


What can go wrong if IDOR exists

IDOR vulnerabilities can lead to:

  • Exposure of personal data
  • Viewing or modifying invoices and orders
  • Unauthorized file downloads
  • Account takeover chains
  • Privilege escalation
  • Financial loss
  • Legal and compliance issues
  • Loss of user trust

IDOR bugs are often simple but extremely damaging.


How attackers usually discover IDOR

Attackers don’t need advanced tools. They often:

  • Change numbers up or down
  • Guess IDs
  • Automate ID enumeration
  • Inspect browser requests
  • Analyze mobile app traffic
  • Replay API calls with modified parameters

If IDs follow patterns, attackers will find them.


Red flags that suggest IDOR exists

  • IDs increase sequentially (1001, 1002, 1003)
  • Changing an ID returns different user data
  • No error when accessing someone else’s resource
  • Frontend hides data but backend still returns it
  • Same token can access multiple users’ objects
  • APIs return 200 OK instead of 403/404

Green flags that show good protection

  • Server checks ownership every request
  • Unauthorized access returns 403 or 404
  • Authorization logic is centralized
  • Logs show blocked access attempts
  • Tests cover object-level permissions
  • IDs are validated against user context

How to properly prevent IDOR (the right way)

1. Enforce authorization on the server

Never trust:

  • URLs
  • Frontend logic
  • Mobile apps
  • Client-side checks

The server must decide every time.


2. Always verify ownership

Before returning or modifying data, ask:

  • “Does this user own this object?”
  • “Is this role allowed to access it?”

If not — deny.


3. Deny by default

If access is not explicitly allowed, block it.


4. Centralize access control

Put authorization checks in:

  • Middleware
  • Service layers
  • Policy engines

Avoid repeating logic everywhere.


5. Use non-predictable IDs (as defense, not a fix)

Random IDs reduce guessing, but they do not replace authorization.


6. Monitor and log aggressively

Track:

  • Sequential ID access
  • Repeated denied requests
  • Token reuse across objects
  • Unusual access patterns

7. Test authorization continuously

  • Unit tests for ownership
  • Integration tests for access control
  • Security testing in CI/CD
  • Regular penetration testing

Testing for IDOR (security checklist)

Manual testing

  • Change IDs in URLs
  • Modify JSON request bodies
  • Replay requests with different IDs
  • Test all HTTP methods (GET, POST, PUT, DELETE)

Automated testing

  • API security scanners
  • Custom authorization tests
  • Regression tests for access control bugs

Code example (easy to understand)

Vulnerable version

@app.route("/invoices/<id>")
def get_invoice(id):
invoice = db.get_invoice(id)
return jsonify(invoice)

Why it’s vulnerable:

  • No check for ownership
  • Any user can access any invoice

Secure version

@app.route("/invoices/<id>")
def get_invoice(id):
invoice = db.get_invoice(id)
if invoice.owner_id != current_user.id:
abort(403)
return jsonify(invoice)

Golden rule:

If the object doesn’t belong to the user — block access.


Detection & monitoring rules that actually help

  • Alert on repeated requests with changing IDs
  • Alert when one token accesses many users’ data
  • Log all authorization failures with context
  • Review access logs for enumeration patterns

These signals often expose IDOR exploitation early.


How IDOR fits into MITRE & CWE (simple view)

IDOR is not a standalone attack technique — it’s a weakness that enables attacks.


One-page developer cheat sheet

  • Always check ownership on the server
  • Centralize authorization logic
  • Return 403 or 404 for unauthorized access
  • Don’t rely on hidden UI controls
  • Don’t trust “hard to guess” IDs
  • Test authorization like business logic
  • Monitor access patterns

The one sentence you should remember

IDOR happens when an application lets users access internal objects by ID without verifying whether they’re allowed to access them.

Aegiron

Backed by 11+ years in cybersecurity and incident response, we decode the latest threats shaping today’s digital battlefield. This blog cuts through the noise with clear insights on vulnerabilities, emerging exploits, and the cyber news defenders can’t afford to miss.