highAuthentication

Insecure Direct Object Reference (IDOR)

What Is This Vulnerability?

IDOR vulnerabilities occur when an application exposes internal object identifiers (like database IDs) in URLs or request parameters and does not verify that the authenticated user has permission to access the referenced object. Attackers simply change the ID in the request to access or modify other users' data.

Why It Happens

Applications often use sequential numeric IDs or predictable identifiers in API endpoints (e.g., /api/orders/123). When the backend retrieves the record by ID without checking whether the requesting user owns that record, any authenticated user can access any other user's data by guessing or iterating through IDs.

Example Code

Vulnerableroutes/orders.ts
app.get("/api/orders/:id", requireAuth, async (req, res) => {
  const order = await db.query(
    "SELECT * FROM orders WHERE id = $1",
    [req.params.id]
  );
  if (!order.rows[0]) return res.status(404).json({ error: "Not found" });
  res.json(order.rows[0]);
});
Fixedroutes/orders.ts
app.get("/api/orders/:id", requireAuth, async (req, res) => {
  const order = await db.query(
    "SELECT * FROM orders WHERE id = $1 AND user_id = $2",
    [req.params.id, req.user.id]
  );
  if (!order.rows[0]) return res.status(404).json({ error: "Not found" });
  res.json(order.rows[0]);
});

How Hackers Exploit It

Attackers authenticate with their own account and observe the ID pattern in API responses. They then script requests with incrementing or decrementing IDs to enumerate all records. Tools like Burp Suite's Intruder automate this process. The attacker can download all orders, invoices, messages, or personal data belonging to other users in minutes.

How to Fix It

Always include the authenticated user's ID in database queries as a filter condition. Use UUIDs instead of sequential integers to make IDs harder to guess (but do not rely on this alone). Implement row-level security policies in your database. Create a shared authorization layer or middleware that checks ownership before returning any record.

Frequently Asked Questions

What is the simplest way to prevent IDOR?
Always filter database queries by the authenticated user's ID. Instead of SELECT * FROM orders WHERE id = :orderId, use SELECT * FROM orders WHERE id = :orderId AND user_id = :userId. This ensures users can only access their own records regardless of which ID they provide.
Do UUIDs prevent IDOR attacks?
UUIDs make IDs harder to guess, which raises the bar for enumeration attacks. However, they do not prevent IDOR. If an attacker obtains a valid UUID (through a leak, log exposure, or another endpoint), they can still access the record. Always enforce ownership checks regardless of the ID format.
How can I test for IDOR in my application?
Create two test accounts and log in as each one. Copy API requests from one account and replay them in the other account's session, changing the resource IDs. If you can access or modify resources owned by the first account while authenticated as the second, you have an IDOR vulnerability.

Related Security Topics

Check Your Code for This Vulnerability

Run a free scan to check if your site is affected by insecure direct object reference (idor).