From UUID predictability to multi-tenant parameter tampering in cloud APIs.

A single object ID can become a serious security weakness when an application fails to verify who is allowed to access the requested resource. Attackers may change an ID in a URL, API request, or JSON body to access another user’s information.

This guide provides a complete testing guide for ethical hackers and application developers. It explains how IDOR vulnerabilities work, how to reproduce them in a controlled lab, and how to prevent them in production applications.

  1. What Is an IDOR Vulnerability? Insecure Direct Object Reference (IDOR) is an access-control vulnerability that occurs when an application uses a user-controlled reference to access an object without properly checking whether the user is authorized to access it.

For example, consider this API endpoint:

GET /api/users/101/profile
The application returns the profile belonging to user ID 101.

If an authenticated user changes the ID:

GET /api/users/102/profile
and receives another user’s private information, the application may have an IDOR vulnerability.

IDOR commonly affects:

User profiles and account details
Invoices and payment records
Documents and downloadable files
Cloud storage objects
Customer records in multi-tenant applications
REST and GraphQL APIs
IDOR is closely related to Broken Object Level Authorization (BOLA), listed as OWASP API Security Top 10 API1:2023.

  1. How IDOR Attacks Work: UUIDs and Multi-Tenant APIs IDOR does not depend on whether an identifier is numeric, random, or difficult to guess. The main problem is missing authorization.

Predictable identifiers

Some applications use sequential IDs such as:

/api/invoices/1001
/api/invoices/1002
/api/invoices/1003
If the server does not check ownership, changing the number may expose another invoice.

UUID-based identifiers

Applications sometimes use UUIDs:

/api/documents/550e8400-e29b-41d4-a716-446655440000
UUIDs make identifiers harder to guess, but they do not replace access-control checks. A leaked UUID can still be used by an unauthorized person if the server accepts it without verifying permissions.

Multi-tenant parameter tampering

Consider a cloud application where customers belong to different organizations.

A request might contain:

GET /api/reports?tenant_id=company_101
An attacker may try changing the parameter:

GET /api/reports?tenant_id=company_102
If the server trusts the supplied tenant ID instead of deriving the permitted tenant from the authenticated user’s session, data from another organization could be exposed.

  1. Build a Local IDOR Testing Lab Use a local application or an authorized Docker lab. Never test against systems without permission.

Create a file named app.py:

from flask import Flask, jsonify, request
app = Flask(name)

Demo-only user records

DOCUMENTS = {
101: {"owner": "alice", "title": "Alice Report"},
102: {"owner": "bob", "title": "Bob Report"}
}

Demo-only authentication tokens

TOKENS = {
"alice-token": "alice",
"bob-token": "bob"
}
def current_user():
token = request.headers.get("Authorization", "")
token = token.replace("Bearer ", "", 1)
return TOKENS.get(token)

Vulnerable: does not check document ownership

@app.get("/vulnerable/documents/int:doc_id")
def vulnerable(doc_id):
document = DOCUMENTS.get(doc_id)
if not document:
return jsonify({"error": "Not found"}), 404
return jsonify(document)

Remediated: checks ownership before returning data

@app.get("/secure/documents/int:doc_id")
def secure(doc_id):
user = current_user()
if not user:
return jsonify({"error": "Unauthorized"}), 401
document = DOCUMENTS.get(doc_id)
if not document or document["owner"] != user:
return jsonify({"error": "Not found"}), 404
return jsonify(document)
if name == "main":
app.run(host="127.0.0.1", port=5000, debug=False)
Install Flask:

python -m pip install flask
Start the application:

python app.py
The local application runs at:

http://127.0.0.1:5000

  1. Test the Vulnerability Using CLI Commands Use two demo identities: Alice and Bob.

Download the Medium App
Test 1: Access the vulnerable endpoint

curl -i http://127.0.0.1:5000/vulnerable/documents/102
Expected result: the endpoint returns Bob’s document even though the request does not establish ownership.

Test 2: Access the secure endpoint as Alice

curl -i \
-H "Authorization: Bearer alice-token" \
http://127.0.0.1:5000/secure/documents/102
Expected result:

{
"error": "Not found"
}
Test 3: Access Alice’s own document

curl -i \
-H "Authorization: Bearer alice-token" \
http://127.0.0.1:5000/secure/documents/101
Expected result:

{
"owner": "alice",
"title": "Alice Report"
}
Test 4: Access Bob’s document as Bob

curl -i \
-H "Authorization: Bearer bob-token" \
http://127.0.0.1:5000/secure/documents/102
Expected result: Bob receives his own document.

The vulnerable endpoint demonstrates missing ownership checks. The remediated endpoint verifies the authenticated user before returning the requested object.

  1. Prevention, Security Checklist and Further Testing Developers should enforce authorization on the server for every request that accesses a protected object.

Recommended security practices:

Verify object ownership or permissions on every API request.
Derive tenant identity from trusted authentication context.
Never trust user-supplied IDs as proof of authorization.
Apply authorization checks to read, update, delete, and download operations.
Use role-based or attribute-based access controls where appropriate.
Return only the information required by the application.
Log and investigate repeated unauthorized access attempts.
Add automated authorization tests to CI/CD pipelines.
Ethical testing checklist

Test with two authorized demo accounts.
Change object IDs and tenant parameters in the local lab.
Compare responses from the vulnerable and remediated endpoints.
Verify that one user cannot access another user’s documents.
Test read and write operations separately.
Record evidence and document the affected endpoint.
Retest after applying the fix.
Relevant security references

OWASP API1:2023 — Broken Object Level Authorization: https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/
OWASP Web Security Testing Guide: https://owasp.org/www-project-web-security-testing-guide/
CWE-639 — Authorization Bypass Through User-Controlled Key: https://cwe.mitre.org/data/definitions/639.html
Final Takeaway

IDOR is not simply an issue of predictable IDs. It is a failure to enforce authorization at the object level. UUIDs, hidden URLs, and frontend restrictions cannot replace server-side permission checks. Every request must verify that the authenticated user is allowed to access the requested resource.

Explore application security testing with Hack My Website.