29. OWASP Top 10 Web Vulnerabilities
29.5 A01 Broken Access Control and IDOR
In short: Broken access control is the #1 risk: a user can do or see things they should not.
Broken access control is the #1 risk: a user can do or see things they should not. IDOR (Insecure Direct Object Reference) is the classic case – changing an ID in a URL to read someone else's data.
You see: https://app.com/invoice?id=1001 (your invoice)
You try: https://app.com/invoice?id=1002 (someone else's – and it shows!)
The server showed the record without checking that it belongs to you. This is horizontal escalation (Chapter 26) at the application level.
The fix – always check ownership and role on the server:
// after loading the record, confirm it belongs to the logged-in user
$stmt = $pdo->prepare("SELECT * FROM invoices WHERE id = ? AND user_id = ?");
$stmt->execute([$_GET['id'], $_SESSION['user_id']]);
if (!$row = $stmt->fetch()) { http_response_code(403); exit('Forbidden'); }
Never rely on hiding a button or a menu – enforce every permission on the server, for every request.
Ravindra Bagale's Tip
"The admin page link isn't visible to normal users, so it's safe" is the biggest misconception. An attacker doesn't need the link – they type the URL directly! Check role and ownership on the server for every request. In the Reels app, confirm on the server that one user cannot delete another user's post.
Ravindra Bagale's Tip – मराठी
"Admin page चा link normal user ला दिसत नाही, म्हणून सुरक्षित आहे" हा सर्वात मोठा गैरसमज. Attacker ला link नको, तो थेट URL type करतो! प्रत्येक request ला server वर role आणि ownership तपासा. Reels app मध्ये एक user दुसऱ्याची post delete करू शकणार नाही, हे server वर confirm करा.
Ravindra Bagale's Tip – हिंदी
"Admin page का link normal user को नहीं दिखता, इसलिए सुरक्षित है" यह सबसे बड़ी गलतफ़हमी है. Attacker को link नहीं चाहिए, वह सीधे URL type करता है! हर request पर server पर role और ownership जाँचो. Reels app में एक user दूसरे की post delete नहीं कर सकता, यह server पर confirm करो.
Lab
In Juice Shop, log in and try to view another user's basket by changing the id in the request (Burp). In your reels app, add an ownership check to every action (view, edit, delete) and confirm one user cannot touch another's posts.