Insecure Direct Object Reference (IDOR)
Also Known As
Insecure Direct Object Reference
object reference vulnerability
TL;DR
A user accesses another user's data by changing an ID in a URL or request — no authorisation check performed.
Explanation
IDOR occurs when an application exposes internal object identifiers (database IDs, filenames) directly in requests and does not verify that the requesting user is authorised to access that object. Example: /invoice?id=1234 — incrementing the ID to 1235 returns another user's invoice. Prevention: always verify that the authenticated user owns or has permission to access the requested resource, server-side, on every request.
How It's Exploited
GET /api/orders/1337
# If order 1337 belongs to another user and there's no ownership check,
# attacker reads their private data by incrementing the ID
# If order 1337 belongs to another user and there's no ownership check,
# attacker reads their private data by incrementing the ID
Diagram
flowchart TD
USER2[Logged in as User 42] --> REQ3[GET /api/invoices/100]
REQ3 --> CHECK2{Check: does user 42<br/>own invoice 100?}
CHECK2 -->|no check!| RETURN2[Returns invoice 100<br/>belongs to user 99!]
subgraph Fix3
AUTH3[Authorisation check<br/>SELECT WHERE id=100 AND user_id=42]
ZERO[0 rows = 404 Not Found<br/>never reveal resource exists]
end
style CHECK2 fill:#f85149,color:#fff
style RETURN2 fill:#f85149,color:#fff
style AUTH3 fill:#238636,color:#fff
Common Misconception
✗ Using UUIDs instead of sequential IDs prevents IDOR. UUIDs prevent guessing but not IDOR — if authorisation checks are missing, an attacker who obtains any valid UUID can still access it freely.
Why It Matters
IDOR lets attackers access any user's data by simply changing an ID in the URL or request body. It is one of the most common API vulnerabilities because it is invisible to automated scanners and requires no special tools to exploit.
Common Mistakes
- Assuming sequential IDs are "hard to guess" — automated tools enumerate thousands of IDs per second.
- Checking authentication but not ownership — verifying a user is logged in does not verify they own the resource.
- Using UUIDs and believing that makes IDOR impossible — obscurity without authorisation checks is not security.
- Only protecting read endpoints and forgetting update and delete routes.
Code Examples
✗ Vulnerable
// No ownership check — any user can view any order
public function show(int \$orderId): JsonResponse {
return response()->json(Order::findOrFail(\$orderId));
}
✓ Fixed
public function show(int \$orderId): JsonResponse {
\$order = Order::findOrFail(\$orderId);
// Enforce ownership — compare to authenticated user
if (\$order->user_id !== auth()->id()) {
abort(403); // Forbidden — not just 404
}
return response()->json(\$order);
}
// Or scope query to current user (prevents the object being fetched at all)
\$order = auth()->user()->orders()->findOrFail(\$orderId);
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
13 Mar 2026
Edited
22 Mar 2026
Views
33
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Ahrefs 9
Perplexity 8
Amazonbot 7
Unknown AI 3
Majestic 1
Google 1
Also referenced
How they use it
crawler 28
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Low
⚡ Quick Fix
After loading a resource by ID, always check: $resource->user_id === auth()->id() — never trust that the ID alone grants access
📦 Applies To
PHP 5.0+
web
api
🔗 Prerequisites
🔍 Detection Hints
->find($_GET['id']) or findOrFail($id) with no subsequent ownership check
Auto-detectable:
✗ No
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: High
Context: File
Tests: Update
CWE-284
CWE-639