If you have never heard of access control vulnerabilities before, you are in exactly the right place — this step gives you everything you need before the hands-on exercise begins.
What is access control?
Almost every web application stores data that belongs to specific people. When you open a notes app and log in, you expect to see your notes — not your colleague's, not your manager's, and certainly not the administrator's confidential files.
Access control is the set of rules the server uses to decide who can see or change each piece of data. A correct implementation ensures that Alice can only read Alice's notes. A broken implementation lets Alice read anyone's notes simply by changing a number in the URL.
What is Broken Access Control?
Broken Access Control is the #1 vulnerability in the OWASP Top 10 (A01:2021). OWASP (the Open Worldwide Application Security Project) is a nonprofit organisation that publishes the most widely-used security guides and standards in the industry. Broken Access Control has held the top position since 2021 because it appears in a large proportion of real applications and because its impact is severe — it directly exposes other users' data.
The category covers many related weaknesses. This lesson focuses on the most direct and teachable sub-type: IDOR.
What is IDOR?
IDOR stands for Insecure Direct Object Reference. The name describes exactly what happens:
- A web application gives you a direct reference to a database object — a raw number like
3that is the note's ID in the database. - You can change that reference: type
7instead of3. - The server fetches note 7 and returns it — without checking whether you own it.
The "insecure" part is not the number in the URL. The insecurity is the missing check on the server.
Normal request: GET /notes/3 → Alice's own note ✓ (she owns note 3)
Manipulated: GET /notes/7 → Admin's private note ✓ (server never checks ownership)Why does this happen?
A developer wrote code to look up a note by its ID:
note = db.query(Note).filter(Note.id == note_id).first()
return noteThis code is functionally correct — it retrieves the right note. What is missing is a single additional line:
if note.owner_id != current_user.id:
raise HTTPException(status_code=403, detail="Forbidden")Without that check, any logged-in user can access any note in the database. The bug is easy to overlook because the application works perfectly for legitimate users — they only ever click their own notes.
Why this matters
IDOR has been exploited in real applications to expose millions of users' data:
- A large social network exposed private photos because photo IDs were sequential integers.
- A payment platform exposed transaction histories because receipt IDs could be incremented.
- A government health records system exposed sensitive patient data through guessable document IDs.
On bug bounty platforms, IDOR is consistently among the most-reported and highest-paid vulnerability classes — because it directly grants unauthorised access to real user data.
What you will do in this lesson
You will attack a purpose-built practice application called NoteVault — a fictional private note-storage service deliberately built with a missing ownership check.
Your goal: log in as a regular user, observe the URL pattern when viewing your own notes, then change the note ID to access the administrator's confidential note. You will capture the challenge flag hidden inside that note and submit it to complete the lesson.
Everything happens in your browser. No tools to install, no terminal required.