Insecure Direct Object Reference (IDOR)

Just because you have a key to the building, doesn't mean you can open every door.

The idea

IDOR occurs when an application provides direct access to objects based on user-supplied input (like a URL parameter), but fails to verify if the user requesting the object actually owns it or has permission to view it. Simply being logged in (Authenticated) does not mean you are Authorized.

Step 1: Alice clicks "My Profile" and loads /api/users/100.

How it works (Enforcing Ownership)

Never trust the `user_id` passed by the client. Always check the requested object against the `user_id` stored securely in the server-side session or JWT.

# VULNERABLE: IDOR
@app.route("/api/invoices/<invoice_id>")
def get_invoice(invoice_id):
    # DANGER: Fetches the invoice without checking who owns it!
    # Anyone who guesses the invoice_id can download it.
    invoice = db.query(Invoice).get(invoice_id)
    return invoice.to_json()

# SECURE: Authorization Check
@app.route("/api/invoices/<invoice_id>")
@login_required
def get_invoice(invoice_id):
    invoice = db.query(Invoice).get(invoice_id)
    
    # Crucial step: Verify ownership!
    if invoice.owner_id != current_user.id:
        return "403 Forbidden", 403
        
    return invoice.to_json()

Watch out for

Worked example

A banking app allows users to view their statements at `/statements?account=987654321`. A user realizes that changing the URL to `?account=987654322` allows them to view a stranger's bank statement. Because the database uses sequential IDs, the attacker writes a simple script to loop from `000000000` to `999999999`, downloading millions of financial records. This is a classic IDOR breach.

Check yourself

Does switching all database primary keys from auto-incrementing integers (1, 2, 3...) to UUIDs (e.g. 550e8400-e29b-41d4-a716-446655440000) fix an IDOR vulnerability?

No. While they are impossible to guess, UUIDs frequently leak (in referer headers, logs, screen shares, or shared links). Relying on secrecy instead of authorization is "Security through Obscurity".
Correct! UUIDs are a great defense-in-depth measure, but you still MUST perform authorization checks on every request.