पाठ 4 / 25

Object-Level Authorisation (IDOR)

Check ownership on every access.

Never trust the ID in the request

An insecure direct object reference (IDOR) happens when an application uses an identifier from the request (an order ID, a file name) without checking that the current user may access that object. Changing /api/orders/1001 to /api/orders/1002 then returns someone else's data. Fix it by scoping every query to the authenticated user or checking permissions on the loaded object, deny by default, and write tests that try to access other users' resources. Unguessable IDs reduce discovery but do not replace authorisation.

Who may do what, to which data

Access control enforces permissions on every request; server-side request forgery abuses the server's own network access.

Three ideas: object-level checks, function-level checks and CORS, SSRF.
Figure 2.1 — Object checks, function checks and SSRF.

Vulnerable and fixed endpoint

Python (Flask-style sketch).

# VULNERABLE: any logged-in user can read any order
@app.get("/api/orders/<int:order_id>")
@login_required
def get_order(order_id):
    order = db.get(Order, order_id)
    return order.to_dict()

# FIXED: the query is scoped to the current user; 404 avoids confirming existence
@app.get("/api/orders/<int:order_id>")
@login_required
def get_order(order_id):
    order = db.query(Order).filter_by(id=order_id, owner_id=current_user.id).first()
    if order is None:
        abort(404)
    return order.to_dict()

Centralise authorisation

A shared policy layer or helper (for example "can(user, action, resource)") is easier to review than checks scattered across handlers.

त्वरित जाँच: What is the correct fix for an IDOR vulnerability?

  • Hide the ID in the URL
  • Check on the server that the current user may access the requested object
  • Use POST instead of GET
  • Disable caching
Answer

Check on the server that the current user may access the requested object — Authorisation on every request.