Let's imagine our target is a project management application: https://projects.example.com.
Create accounts with the same role to test horizontal privilege escalation:
- Attacker Account:
attacker_user@mail.com - Victim Account:
victim_user@mail.com
Also create accounts with different roles if available (User vs. Admin) to test vertical privilege escalation.
Explore the application and note features that handle user-specific data:
On projects.example.com, you might find:
- Project Access:
GET /projects/123(View project details) - User Profiles:
GET /users/456(View user profile) - File Downloads:
GET /files/789(Download attached files) - API Endpoints:
GET /api/tickets/321(View support tickets) - Settings:
POST /settings/profile/update(Update profile settings)
Best initial targets: Project access, file downloads, and user profile endpoints.
Using Burp Suite or browser dev tools, intercept traffic while browsing as your attacker account.
Scenario 1: Horizontal IDOR
- As
attacker_user, you access your project atGET /projects/1001 - Intercept the request and see:
GET /projects/1001 HTTP/1.1 Host: projects.example.com Cookie: session=attacker_session_token
- Change the ID to
1002(victim's project you shouldn't access):GET /projects/1002 HTTP/1.1 Host: projects.example.com Cookie: session=attacker_session_token
- If successful: You can now view the victim's private project! IDOR Found!
Scenario 2: Vertical IDOR
- As a regular user, you find an admin endpoint:
GET /admin/users/500/reports - Intercept and modify:
GET /admin/users/500/reports HTTP/1.1 Host: projects.example.com Cookie: session=regular_user_session
- If successful: A regular user can access admin functionality!
Scenario 3: POST Request IDOR
POST /projects/update HTTP/1.1
Host: projects.example.com
Content-Type: application/json
Cookie: session=attacker_session_token
{"project_id": 1001, "name": "My Project", "description": "Updated description"}Change "project_id": 1001 to "project_id": 1002 - can you modify someone else's project?
If direct ID swapping doesn't work, try these techniques:
-
Encoded/Hashed IDs:
1001→MTAwMQ==(base64) → Try decoding/encoding1001→3e9(hex) → Convert between number formats1001→1f5acd38a(hash) → Check if predictable
-
UUID Prediction: If IDs are UUIDs like
550e8400-e29b-41d4-a716-446655440000, check if they're sequential or time-based -
Add Missing Parameters: Sometimes the app doesn't validate if you add an ID parameter:
GET /api/projects HTTP/1.1 # Normally lists your projects
Try:
GET /api/projects?user_id=500(add parameter that wasn't there) -
Change HTTP Methods:
GET /projects/1001→POST /projects/1001POST /projects/delete→DELETE /projects/1001
-
Parameter Pollution:
GET /projects/1001?user_id=1001&user_id=1002
Or:
GET /projects/1001?user_id=1002
-
Change File Types/Endpoints:
GET /projects/1001→GET /api/projects/1001GET /projects/1001→GET /projects/1001.json
- Export Features: Check if data exports contain other users' information
- Email Notifications: Do action notifications reveal sensitive IDs or data?
- Search Functions: Can you search and find other users' data?
- API Responses: Even if the UI hides data, the API might return it
Example: A "Export My Data" feature might create a CSV with project IDs that you can then use to access other projects directly.
Impact: An attacker can:
- Access confidential project data belonging to any user
- Steal intellectual property, financial information, or business secrets
- Potentially modify or delete unauthorized projects (if write endpoints are also vulnerable)
- Mass-harvest all project data by iterating through project IDs
Remediation Recommendations:
- Implement Proper Authorization: Add server-side checks to verify the authenticated user has permission to access the requested resource
- Use Indirect References: Replace direct object references with mapped, unpredictable tokens
- Apply Role-Based Access Control: Ensure users can only access resources within their permission scope
- Conduct Security Testing: Regularly test all object reference endpoints for authorization flaws
Additional Vulnerable Endpoints:
/api/projects/{project_id}/files/projects/{project_id}/settings/users/{user_id}/profile
- Automate with Tools: Use Burp Intruder to fuzz numeric parameters sequentially
- Check Everything: Test GET, POST, PUT, DELETE methods on all object references
- Look for Patterns: IDs in URLs, request bodies, headers, and even file names
- Chain with Info Disclosure: Use information leaks from one endpoint to fuel IDOR attacks on another
- Test Mass Assignment: Sometimes changing
user_idisn't needed - the app might use your session, but you can specify other users in POST bodies