IDOR — Predictable Resource ID
Easy Broken Access Control · A01:2021 20 min
IDOR — Predictable Resource ID
Scenario
AcmeBilling lets each customer view their own invoices at ?invoice=<number>. The application does not check whether the invoice belongs to the user — it just returns whatever invoice has that ID.
You are logged in as customer #14 with access to invoice #1042. There is another invoice somewhere in the system that contains a flag value. Find it.
The flag has the shape TC{idor_…}.
Primer — why this works
The app does, server-side:
function getInvoice(id) {
return db.invoices.find(inv => inv.id === Number(id)); // ← no ownership check
}
A real fix would compare inv.customer_id === currentUser.id before returning the row. Without that check, anyone can request anyone else's invoice by guessing the ID.
Steps
- Open the lab. Note that
?invoice=1042shows your own invoice. - Change the number in the URL. Try sequential values — 1041, 1043, 1044…
- One of the invoices contains the flag string.
- Paste the flag below.
Tips
- IDs in this lab live in the range 1040–1060. You don't need a script — six clicks will do.
- In a real engagement you'd note this as CWE-639: Authorization Bypass Through User-Controlled Key.
Acceptance
- You find the invoice that contains a
TC{idor_…}payload. - Submitted hash matches.
Hints
Hint 1 (−10 pts)
Try changing the `invoice` number in the URL. The IDs are sequential integers near 1042.
Hint 2 (−10 pts)
Walk the range 1040–1060. The flag is on one of these invoices. Use the browser back/forward buttons to scan quickly.
Hint 3 (−10 pts)
Invoice ID 1051 is the one. Open `?invoice=1051` and copy the `TC{idor_…}` string from the line items.
Lab environment · sandboxed iframe · auto-resets every 60 min