![]() |
| Ethical Hacking |
🛡️ Ethical Hacking — Day 23
Broken Access Control, IDOR & BOLA — Authorization Testing Lab
⚠️ LEARNING PURPOSE ONLY: This tutorial is strictly for educational and defensive cybersecurity learning. Perform every practical exercise only against your local OWASP Juice Shop lab, applications you own, or systems for which you have explicit authorization. Never access another person's data or modify permissions on systems without explicit authorization.
Welcome to Day 23.
Yesterday we learned:
Authentication
Sessions
Cookies
Login security
MFA
Password reset
Session invalidation
Today we move to one of the most important concepts in web application security:
🔐 Authorization
Authentication asks:
Who are you?
Authorization asks:
What are you allowed to access or perform?
A user can be correctly authenticated and still be able to access something they shouldn't.
🎯 Today's Learning Objectives
You'll learn:
Authentication vs authorization
Broken Access Control
IDOR
BOLA
Horizontal privilege escalation
Vertical privilege escalation
Object-level authorization
Function-level authorization
API authorization
Role-based access control
Ownership checks
Burp Repeater testing
Safe authorization testing
Laravel authorization
Spring Security authorization
Linux practical commands
Windows PowerShell practical commands
macOS practical commands
How to write an access-control finding
1. Authentication vs Authorization
Remember:
AUTHENTICATION
↓
"Who are you?"
↓
Identityversus:
AUTHORIZATION
↓
"What can you do?"
↓
PermissionsExample:
User A
↓
Authenticated ✓
↓
GET /profile
↓
Allowed ✓But:
User A
↓
Authenticated ✓
↓
GET /admin/users
↓
Should be denied ✗2. What Is Broken Access Control?
Broken access control occurs when an application fails to properly enforce what an authenticated user is allowed to access or perform.
Conceptually:
User
↓
Authentication ✓
↓
Authorization check
↓
❌ Missing / Incorrect
↓
Protected resourceThe security problem isn't necessarily the login system.
The problem is the permission decision.
3. Real-World Example
Imagine:
GET /api/users/100User 100 owns that record.
User 101 logs in and requests:
GET /api/users/100If the server simply checks:
"Is the requester logged in?"instead of:
"Is the requester allowed to access user 100?"there may be an authorization vulnerability.
4. IDOR
IDOR means:
Insecure Direct Object Reference
It traditionally refers to situations where an application exposes an object reference such as:
/users/100
/orders/500
/invoices/200
/documents/15and fails to verify whether the current user is authorized to access that object.
Modern OWASP terminology often discusses this under Broken Access Control and BOLA — Broken Object Level Authorization.
5. BOLA
BOLA is particularly relevant to APIs.
Example:
GET /api/orders/100The server receives:
Object ID = 100It must determine:
Is the authenticated user allowed to access order 100?Not merely:
Is the user authenticated?6. Authorization Decision
A secure authorization decision resembles:
Authenticated User
│
▼
Request
│
▼
Resource = Order 100
│
▼
Ownership / Permission Check
│
┌───┴───┐
▼ ▼
ALLOW DENY7. Horizontal Privilege Escalation
Horizontal escalation means:
A user accesses another user's resources at approximately the same privilege level.
Example:
User A
↓
Own Profile
↓
/users/101Then attempts:
/users/102If user 101 can access user 102's private information without authorization, that's a potential horizontal access-control issue.
8. Vertical Privilege Escalation
Vertical escalation means:
A lower-privileged user accesses functionality intended for a higher-privileged role.
Example:
Normal User
↓
/admin/usersIf the server allows it:
User
↓
Admin Functionthat's a serious authorization problem.
9. Example Role Model
Imagine:
ADMIN
├── Manage users
├── Manage products
├── View reports
└── Configure system
MANAGER
├── Manage assigned products
└── View reports
USER
├── View own profile
└── Create own ordersThe server must enforce these rules.
10. Never Trust the UI
Suppose the UI hides:
Delete Userfrom normal users.
That doesn't provide real security.
An attacker may still manually send:
DELETE /api/users/100Therefore:
Authorization must be enforced server-side.
11. Start Your Lab
Linux
docker psWindows PowerShell
docker psmacOS
docker psVerify:
Linux/macOS
curl -I http://127.0.0.1:3000Windows
curl.exe -I http://127.0.0.1:300012. Start Burp Suite
Open:
Burp Suite
↓
Proxy
↓
Open BrowserNavigate to:
http://127.0.0.1:3000Keep your testing scope limited to:
127.0.0.1:3000🧪 Practical Lab 1 — Find Object References
After logging into your local Juice Shop account, browse normally.
Open:
Proxy
↓
HTTP historyLook for requests containing:
/users//orders//products//reviews/or JSON fields such as:
{
"id": 123
}Don't assume a particular endpoint exists. Analyze the requests generated by your local application.
13. Build an API Map
Create:
Feature Endpoint Object ID
-------------------------------------------------
Profile _____________ _____
Order _____________ _____
Product _____________ _____
Review _____________ _____
Other _____________ _____You're learning to recognize object references.
14. Send a Request to Repeater
Choose a request involving your own test data.
Right-click:
Send to RepeaterThen:
Repeater
↓
SendRecord the baseline:
Status:
Response size:
Object:
Authenticated user:15. Don't Attack Random IDs
For today's exercise, don't blindly enumerate:
1
2
3
4
5
...
10000Instead, use:
Your own test account
Your own test objects
Known local lab dataThe purpose is to understand authorization—not to collect other users' information.
16. Safe Object Authorization Test
Suppose your own account owns:
Order 100Your baseline:
GET /orders/100returns:
200 OKNow, only if your local lab contains another deliberately created test account/object, compare behavior using that controlled object.
For example:
GET /orders/101Observe whether the application returns:
403 Forbiddenor:
404 Not Foundor another appropriate denial.
Don't modify or access data belonging to real users.
17. Why 403 vs 404?
An application might return:
403 Forbiddenmeaning:
You are authenticated, but not allowed.
Or:
404 Not Foundto avoid revealing whether the object exists.
Both can be valid design choices depending on the application's security and information-disclosure requirements.
18. What Would Be a Finding?
Imagine:
User A
↓
Own object: 100
↓
GET /objects/100
↓
200 OKThen:
User A
↓
Object belonging to User B: 101
↓
GET /objects/101
↓
200 OKand the server returns User B's private information.
That is a strong indication of a BOLA/IDOR-style authorization issue.
19. Important Distinction
Don't conclude:
Different ID
+
200 OK
=
IDORYou need to establish:
Who owns the object?
Who is requesting it?
What should the requester be allowed to do?
What data was returned?Evidence matters.
20. Horizontal Testing
Use two local lab accounts if your environment supports it.
Conceptually:
Account A
↓
Object Aand:
Account B
↓
Object BTest:
Account A → Object A → Expected ALLOW
Account A → Object B → Expected DENY
Account B → Object B → Expected ALLOW
Account B → Object A → Expected DENYThis is one of the cleanest ways to understand object-level authorization.
21. Authorization Matrix
Create:
| Requester | Object | Expected | Actual |
|---|---|---|---|
| User A | Object A | Allow | ___ |
| User A | Object B | Deny | ___ |
| User B | Object A | Deny | ___ |
| User B | Object B | Allow | ___ |
This is far better than random testing.
22. Vertical Testing
Now think about roles.
Create a conceptual matrix:
| Role | Normal Function | Manager Function | Admin Function |
|---|---|---|---|
| User | ✓ | ✗ | ✗ |
| Manager | ✓ | ✓ | ✗ |
| Admin | ✓ | ✓ | ✓ |
The server must enforce this matrix.
23. UI vs Server
Suppose a normal user doesn't see:
Admin DashboardYou should still ask:
Does the server enforce the restriction?Because:
Hidden button
≠
Authorization24. Function-Level Authorization
Authorization isn't only about objects.
It also applies to functions.
Examples:
POST /users
DELETE /users/10
PUT /settings
POST /admin/reportsThe server should determine:
Can this user perform this action?25. HTTP Methods Matter
A resource might support:
GET
POST
PUT
PATCH
DELETEAuthorization may differ by operation.
Example:
GET /profile
→ allowed
PUT /profile
→ allowed
DELETE /profile
→ restrictedNever assume:
"If I can read it, I can modify it."
26. API Authorization
For APIs, think:
Identity
+
Object
+
Action
+
Role
+
OwnershipFor example:
User A
wants to
DELETE
Order 100The server should check:
Is User A allowed to DELETE Order 100?27. Broken Function-Level Authorization
Example:
Normal user:
POST /api/profileallowed.
But:
Normal user:
POST /api/admin/create-usershould be denied.
If the application checks only authentication:
Logged in? YESinstead of authorization:
Admin? NOthere may be a vulnerability.
28. Laravel Authorization
Laravel provides mechanisms such as:
Gates
Policies
MiddlewareConceptually:
$this->authorize('update', $post);The important principle:
Request
↓
Authenticated User
↓
Policy Check
↓
Allow / DenyDon't rely only on hiding UI elements.
29. Laravel Policy Example
Conceptually:
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}This implements an ownership rule:
Current User
=
Post OwnerThen:
ALLOWotherwise:
DENY30. Spring Security
Spring Security supports authorization using:
Roles
Authorities
Method Security
Request AuthorizationFor example:
@PreAuthorize("hasRole('ADMIN')")This can protect an administrative operation.
But object-level authorization may still require an ownership check.
31. Role Check Isn't Always Enough
Consider:
ROLE_USERBoth User A and User B have the same role.
A role check alone cannot determine:
Does User A own Object B?You may need:
Role
+
Ownership32. Ownership Check
Secure logic:
Current User
│
▼
Object requested
│
▼
Object.owner_id
│
▼
Compare IDs
│
┌──┴──┐
▼ ▼
Match No Match
│ │
ALLOW DENY33. Don't Trust User-Supplied Owner IDs
A dangerous design might accept:
{
"owner_id": 100
}and simply trust it.
The server should derive ownership from the authenticated identity where appropriate.
Conceptually:
Authenticated User ID
↓
Server-side ownershiprather than:
Client-supplied owner_id
↓
Trust34. Mass Assignment Connection
This connects to another vulnerability class.
Imagine:
{
"name": "Rohit",
"role": "admin"
}If a normal user can submit:
role = adminand the application blindly updates it, there may be a serious authorization issue.
Frameworks provide mechanisms to restrict which fields users can modify.
35. Safe API Design
Instead of trusting:
{
"user_id": 123,
"role": "admin"
}the server should determine:
Current authenticated identity
+
Allowed fields
+
Server-side authorization36. Linux Practical Session
Check your lab:
docker psInspect headers:
curl -I http://127.0.0.1:3000Verbose request:
curl -v http://127.0.0.1:3000/Through Burp:
curl -x http://127.0.0.1:8080 \
http://127.0.0.1:3000/37. Linux — Save a Response
For your local lab:
curl -s http://127.0.0.1:3000/ > day23.htmlSearch for an object identifier:
grep -n "123" day23.htmlReplace 123 with an identifier relevant to your own lab data.
38. Windows Practical Session
Check:
docker psHeaders:
curl.exe -I http://127.0.0.1:3000Verbose:
curl.exe -v http://127.0.0.1:3000/Through Burp:
curl.exe -x http://127.0.0.1:8080 `
http://127.0.0.1:3000/39. Windows — Search Local Response
curl.exe -s http://127.0.0.1:3000/ -o day23.htmlThen:
Select-String -Path day23.html -Pattern "123"Replace 123 with a relevant test object ID.
40. macOS Practical Session
docker pscurl -I http://127.0.0.1:3000curl -v http://127.0.0.1:3000/Through Burp:
curl -x http://127.0.0.1:8080 \
http://127.0.0.1:3000/41. macOS — Search
curl -s http://127.0.0.1:3000/ > day23.htmlThen:
grep -n "123" day23.htmlAgain, replace the example identifier with one from your own lab.
42. Burp Repeater Authorization Workflow
Use:
Capture request
↓
Send to Repeater
↓
Baseline
↓
Identify object/action
↓
Controlled authorization comparison
↓
Compare response
↓
DocumentDo not automate large-scale enumeration.
43. Response Comparison
Create:
| Request | Status | Size | Data Returned | Expected |
|---|---|---|---|---|
| Own object | ___ | ___ | ___ | Allow |
| Other test object | ___ | ___ | ___ | Deny |
| Admin function | ___ | ___ | ___ | Deny |
| Own update | ___ | ___ | ___ | Allow |
This makes your conclusions evidence-based.
44. BOLA Testing Questions
For each API endpoint ask:
Identity
Who is making this request?Object
Which object is being accessed?Action
What operation is being performed?Ownership
Does the user own this object?Role
Does the user's role allow this action?Result
Did the server enforce the rule?45. Authorization Checklist
Review:
☐ Authentication is required
☐ Authorization checked server-side
☐ Object ownership checked
☐ Role checked
☐ Function permissions checked
☐ Read access controlled
☐ Write access controlled
☐ Delete access controlled
☐ API endpoints protected
☐ Hidden UI isn't treated as security
☐ User-supplied IDs aren't blindly trusted
☐ Sensitive operations require appropriate privileges46. Common Access-Control Mistakes
Mistake 1
if user is logged in:
allow()Too broad.
Better
if authenticated
and authorized_for_resource:
allow()
else:
deny()47. Common Mistake — Client-Side Authorization
Bad design:
if (user.role === "admin") {
showDeleteButton();
}This may control the UI, but the server still needs to enforce:
DELETE /users/100authorization.
48. Common Mistake — Predictable IDs
Sequential IDs:
100
101
102
103aren't automatically a vulnerability.
The real issue is:
Predictable ID
+
Missing authorization
=
Potential access-control vulnerabilityRandom IDs alone don't replace authorization checks.
49. Common Mistake — "It's an Internal API"
Never assume:
/internal/apiis automatically secure.
If an attacker can reach the endpoint, the server must enforce authorization.
50. Common Mistake — Frontend Trust
Never trust:
role=adminsent by the browser.
Never trust:
user_id=123simply because it came from your frontend.
Never trust:
is_admin=truefrom client-controlled input.
Security decisions should be made server-side using trusted identity and authorization data.
51. Day 23 Main Lab
Perform a controlled authorization assessment.
Step 1
Create or identify:
User A
User Busing only your local lab.
Step 2
Create:
Object A
Object Bwhere possible.
Step 3
Capture:
User A → Object AStep 4
Record the baseline.
Step 5
Authenticate as User B.
Step 6
Test the same type of request against your controlled test objects.
Step 7
Build:
User A → Object A → Expected Allow
User A → Object B → Expected Deny
User B → Object B → Expected Allow
User B → Object A → Expected DenyStep 8
Check a privileged function if your lab provides one.
Step 9
Document the results.
📊 Day 23 Authorization Matrix
Fill this out:
╔════════════════════════════════════════════╗
║ DAY 23 ACCESS CONTROL MATRIX ║
╚════════════════════════════════════════════╝
Object A Object B
User A ✓ ✗
User B ✗ ✓
Expected:
User A → Object A: ALLOW
User A → Object B: DENY
User B → Object A: DENY
User B → Object B: ALLOW
Actual:
User A → Object A: __________
User A → Object B: __________
User B → Object A: __________
User B → Object B: __________🧪 Day 23 Security Report
╔══════════════════════════════════════╗
║ DAY 23 — ACCESS CONTROL REPORT ║
╚══════════════════════════════════════╝
Target:
127.0.0.1:3000
Feature:
________________________
Endpoint:
________________________
HTTP Method:
________________________
Requester:
________________________
Object:
________________________
Object Owner:
________________________
Expected Authorization:
________________________
Actual Authorization:
________________________
HTTP Status:
________________________
Data Returned:
________________________
Horizontal Escalation:
Yes / No / Unknown
Vertical Escalation:
Yes / No / Unknown
BOLA / IDOR:
Yes / No / Unknown
Evidence:
________________________
Impact:
________________________
Recommended Fix:
________________________📝 Day 23 Assignment
Answer these questions:
What is authorization?
How is authorization different from authentication?
What is Broken Access Control?
What is IDOR?
What is BOLA?
What is horizontal privilege escalation?
What is vertical privilege escalation?
What is object-level authorization?
What is function-level authorization?
Why isn't hiding a button sufficient security?
Why shouldn't the server blindly trust
user_idfrom the client?Why isn't a predictable ID automatically an IDOR?
Why should authorization be enforced server-side?
Why might an application return 404 instead of 403?
Why does a role check alone sometimes fail to protect an object?
What is an ownership check?
How can Laravel Policies help?
How can Spring Security help?
What is the difference between read and write authorization?
What information should an access-control security report contain?
🏆 Day 23 Challenge
Create this diagram:
AUTHENTICATED USER
│
▼
API REQUEST
│
┌─────────┴─────────┐
│ │
OBJECT ACTION
│ │
└─────────┬─────────┘
▼
AUTHORIZATION CHECK
│
┌──────────┼──────────┐
│ │ │
▼ ▼ ▼
Ownership Role Permission
│ │ │
└──────────┼──────────┘
▼
┌──────┴──────┐
▼ ▼
ALLOW DENYThen add:
Authentication
Session
Audit Logging
Rate Limiting🔐 Day 23 Golden Rules
Rule 1
Authentication tells you who the user is; authorization determines what they can do.
Rule 2
Never rely on the frontend for security decisions.
Rule 3
Every protected object requires an authorization decision.
Rule 4
A valid user session does not mean access to every resource.
Rule 5
Predictable IDs aren't the vulnerability; missing authorization is.
Rule 6
Test authorization with controlled accounts and objects only.
📚 Day 23 Summary
Today you learned:
Authentication vs authorization
Broken Access Control
IDOR
BOLA
Horizontal privilege escalation
Vertical privilege escalation
Object-level authorization
Function-level authorization
API authorization
Ownership checks
Role-based authorization
Laravel Policies
Spring Security
Burp Repeater
Authorization matrices
Linux commands
Windows PowerShell
macOS
Security reporting
🔑 Most Important Lesson
Don't ask only:
"Can this user log in?"
Ask:
"Is this specific user allowed to perform this specific action on this specific resource?"
That question is at the heart of access-control security.
🔜 Day 24 — IDOR/BOLA Practical API Lab
Tomorrow we'll go deeper into:
API object references
BOLA testing methodology
Request/response comparison
Ownership validation
GET vs POST vs PUT vs DELETE authorization
API role checks
Burp Repeater
Laravel API authorization
Spring Security API authorization
Safe two-account lab testing
Linux, Windows & macOS practical sessions
Professional BOLA/IDOR reporting
⚠️ LEARNING PURPOSE ONLY: All exercises remain restricted to your local/authorized environment. Never access or modify another person's data.

No comments:
Post a Comment