← Benteng/case studies
OWASP A01 · Broken Access ControlCWE-639 Authorization Bypass Through User-Controlled KeyHigh

IDOR — reading another tenant's data by changing an id

An endpoint returns any record by id without checking who owns it.

What happened

Insecure Direct Object Reference is the most common access-control bug and access control has been OWASP #1 for four cycles. /api/invoice/1002 → change to 1003 and you read another customer's invoice, because the server trusts the id in the URL and never checks ownership. It passes every scanner because each request is individually 'valid'.

The code

✕ VulnerableAccess control
app.get("/api/invoice/:id", auth, async (req, res) => {
  const inv = await db.invoice(req.params.id);   // no ownership check
  res.json(inv);
});
✓ FixedAccess control
app.get("/api/invoice/:id", auth, async (req, res) => {
  const inv = await db.invoice(req.params.id);
  if (!inv || inv.orgId !== req.user.orgId) return res.sendStatus(404);
  res.json(inv);          // enforce ownership server-side, deny by default
});
→ Detect this class with Attacker vs defender (IDOR)

References

Educational case study. The "vulnerable" snippet is a minimal teaching example, not a working exploit. Benteng · a Palu Gada tool.