OWASP API Security Top 10
API1:2019 - Broken Object Level Authorization
Introduction to Broken Object Level Authorization
Broken Object Level Authorization (BOLA) is one of the most critical vulnerabilities in API security.
This vulnerability occurs when an API request contains an identifier (such as a user ID or object ID),
but the server fails to properly verify whether the requesting user is authorized to access that
specific object.
This vulnerability is also commonly known as IDOR (Insecure Direct Object
Reference). The term refers to situations where objects are referenced directly (usually
through IDs) without proper security checks, allowing unauthorized users to access or manipulate data
belonging to other users.
⚠️ Impact of BOLA Vulnerabilities
The consequences of Broken Object Level Authorization can be severe and include:
- Sensitive Data Leakage: Unauthorized access to confidential user information
- Full Account Takeover: Ability to change passwords or access credentials of other
users
- Password Reset Manipulation: Requesting password resets for other accounts and
receiving them in your own email
- Data Modification: Unauthorized changes to other users' data
- Privacy Violations: Access to personal information without consent
Two Types of Broken Object Level Authorization
BOLA Types Comparison
Type 1
User ID Based
(Most Common)
vs
Type 2
Object ID Based
(Resource Level)
1. User ID Based Authorization
This is the most common type encountered in bug bounty hunting. The vulnerability occurs when user
identifiers are passed as parameters and the server doesn't properly validate ownership. As a hacker or
security tester, you should look for parameters that contain IDs, including hidden parameters that might
not be actively used but could still contain vulnerabilities.
Example: Secure Implementation (Correct)
if (getUserID() == object.ownerID) {
showData();
} else {
echo "You are not allowed to view this data";
wait(5);
redirectToHomePage();
}
Analysis: This is the proper way to handle authorization. The code first checks if
the user is authorized, shows data only if authorized, and handles unauthorized access
appropriately.
Example: Insecure Implementation (Vulnerable)
if (getUserID() != object.ownerID) {
echo "You are not allowed to view this data";
wait(5);
redirectToHomePage();
}
showData(); // This line should never be reached, but...
Vulnerability: This implementation is dangerous because the showData()
function exists after the redirect. If a user presses the back button quickly in certain browsers,
the data might be displayed before the redirect completes. Always place authorized actions inside
the conditional block, never after it.
2. Object ID Based Authorization
This type occurs when object IDs are passed to the server, and the server fails to properly verify
authorization for those specific objects. This commonly happens when developers need to secure some
resources but forget to implement authorization checks on others, especially when dealing with numerous
different object identifiers.
Why This Happens
Developers often have to manage millions of different object identifiers across their application.
With so many endpoints and resources to secure, it's easy to overlook certain areas. This is
particularly common when developers implement security on GET methods but forget to secure POST,
PUT, or DELETE methods for the same resources.
Testing HTTP Methods for BOLA
When testing for Broken Object Level Authorization, it's crucial to test all available HTTP
methods, not just GET requests. Developers frequently implement authorization checks on GET
endpoints but overlook other methods.
GET Method
Retrieve data - Most commonly secured, but still test thoroughly
POST Method
Create new resources - Often forgotten in authorization checks
PUT Method
PATCH Method
Update existing resources - Frequently vulnerable
DELETE Method
Remove resources - Critical if left unsecured
Example Attack Scenarios
Testing Different HTTP Methods on Product Endpoint
GET Request - Retrieve Product Details:
GET /api/v1/products/12345 HTTP/1.1
POST Request - Create New Product:
POST /api/v1/products/12345 HTTP/1.1
PUT Request - Update Product:
PUT /api/v1/products/12345 HTTP/1.1
DELETE Request - Remove Product:
DELETE /api/v1/products/12345 HTTP/1.1
OPTIONS Request - Discover Available Methods:
OPTIONS /api/v1/products/12345 HTTP/1.1
The OPTIONS method reveals all HTTP methods allowed for a specific endpoint, helping you identify
additional attack vectors.
Pro Tip: Using Burp Suite
In Burp Suite Professional, you can easily transform GET requests into POST requests and test
different HTTP methods. This is invaluable for thorough BOLA testing. Right-click on a request and
select "Change request method" to quickly switch between GET and POST.
Detection and Prevention Strategies
How to Detect BOLA Vulnerabilities
Detecting Broken Object Level Authorization requires a deep understanding of the application's business
logic. Here's a systematic approach:
BOLA Detection Workflow
Identify
All Objects
→
Test CRUD
Operations
→
Replace
Object IDs
→
Verify
Authorization
- Understand the Business Logic: Map out all objects and their relationships within
the application
- Test All CRUD Operations: Test Create, Read, Update, and Delete actions on all
objects you are NOT authorized to access
- Replace Object Identifiers: Systematically replace every object ID with IDs from
other users (preferably your own test accounts)
- Test with Multiple Accounts: Create at least two test accounts and attempt to
access resources across accounts
- Replace Authentication Headers: Swap session cookies, JWT tokens, or other
authentication credentials between accounts
Automation Challenges
Automating BOLA detection is challenging because object identifiers are never defined consistently
across applications. You might encounter:
product_id, productId, prod_id
invoice_id, invoiceNumber, invoice_ref
user_id, userId, person_id, account_id
Best Practice for Automation: Instead of trying to detect and replace all object
IDs, replace the JWT token or session cookie of your logged-in user with credentials from another
account you own. This approach works universally across different parameter naming conventions.
Prevention Strategies for Developers
| Strategy |
Implementation |
Benefit |
| Use UUIDs/GUIDs |
Replace sequential IDs with universally unique identifiers |
Makes guessing valid IDs extremely difficult (but not impossible - still need authorization
checks) |
| JWT Token Authentication |
Extract user ID from JWT token on the server side |
User ID is cryptographically signed and cannot be tampered with |
| Never Trust Client Input |
Never accept user ID as a parameter; always derive it from authenticated session |
Eliminates direct manipulation of user identifiers |
| Centralized Authorization |
Create a single authorization service/library used across all endpoints |
Ensures consistent security implementation and easier maintenance |
| Verify All Operations |
Implement authorization checks on Read, Write, Update, and Delete for every private object
|
Comprehensive protection across all actions |
Recommended Implementation Pattern
// Extract user ID from authenticated JWT token (server-side)
const authenticatedUserId = extractUserIdFromJWT(request.token);
// Fetch the requested object
const requestedObject = database.getObject(objectId);
// Verify ownership/authorization
if (requestedObject.ownerId !== authenticatedUserId) {
return response.status(403).json({
error: "Forbidden: You do not have access to this
resource"
});
}
// Proceed with authorized action
return response.status(200).json(requestedObject);
Key Points:
- User ID is extracted from the JWT token, not from request parameters
- Authorization is checked before any data is accessed or returned
- Clear error message without revealing sensitive information
- Return appropriate HTTP status code (403 Forbidden)
Ethical Testing Guidelines
⚠️ Critical Ethical Considerations
As a penetration tester or ethical hacker, you have strict obligations regarding data sensitivity
and responsible disclosure:
Testing Best Practices:
- Always Use Your Own Test Accounts: Never test with real user data or accounts
belonging to actual users
- Create Multiple Test Accounts: Set up at least two accounts under your control
to test authorization between them
- Avoid Production Data: When possible, test in staging or development
environments
- Document Responsibly: Record findings without exposing sensitive information
Non-Disclosure Agreement (NDA) Compliance:
- Never Name the Target: Do not publicly disclose the name of the organization
you're testing
- Generalize Scenarios: When discussing findings, always omit specific details
that could identify the target
- Protect Sensitive Data: Never share, store, or disclose any personal data you
encounter during testing
- Limited Discussion: You can discuss vulnerabilities in general terms but never
reveal exact scenarios or implementations
- Prevent Exploitation: Ensure your reports and findings don't enable other
attackers to exploit the vulnerabilities
Legal Liability:
Failure to follow ethical guidelines can result in:
- Breach of NDA and legal action
- Criminal charges if unauthorized access occurs
- Civil liability for any damages resulting from your testing
- Permanent ban from bug bounty platforms
- Damage to your professional reputation
Example Testing Workflow
- Create Test Account A: Register with email [email protected]
- Create Test Account B: Register with email [email protected]
- Perform Actions as User A: Create objects, note down IDs and authentication
tokens
- Switch to User B: Attempt to access User A's objects using User B's session
- Test All Methods: Try GET, POST, PUT, DELETE with User A's object IDs while
authenticated as User B
- Document Findings: Record successful unauthorized access without exposing real
data
Advanced Testing Techniques
Testing with Different Authentication Mechanisms
JWT Token Replacement
When testing APIs that use JWT (JSON Web Tokens), replace the entire token between accounts:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.USER_A_TOKEN
Replace with:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.USER_B_TOKEN
Then attempt to access User A's resources while authenticated as User B.
Session Cookie Replacement
For session-based authentication, swap cookies between accounts:
Cookie: session_id=abc123-USER-A-SESSION
Replace with:
Cookie: session_id=xyz789-USER-B-SESSION
Parameter Discovery and Testing
Look for object identifiers in various locations:
| Location |
Example |
Testing Approach |
| URL Path |
/api/users/12345/profile |
Replace 12345 with another user's ID |
| Query Parameters |
/api/profile?user_id=12345 |
Change user_id parameter value |
| Request Body |
{"userId": 12345, "action": "view"} |
Modify userId in JSON payload |
| Headers |
X-User-Id: 12345 |
Change custom header values |
| Hidden Parameters |
Parameters not visible in UI |
Discover through proxy tools and test systematically |
Common Identifier Naming Patterns
When hunting for BOLA vulnerabilities, watch for these common parameter names:
User Identifiers
user_id, userId, uid, user, account_id, person_id, customer_id
Object Identifiers
id, object_id, resource_id, item_id, entity_id
Document IDs
doc_id, document_id, file_id, invoice_id, order_id
Product IDs
product_id, prod_id, item_id, sku, catalog_id
Real-World Attack Scenarios
BOLA Attack Flow
Attacker
Authenticates
→
Discovers
Object IDs
→
Manipulates
IDs
→
Accesses
Victim Data
Scenario 1: Account Takeover via Profile Update
Normal Request (Updating Own Profile):
PUT /api/users/100/profile HTTP/1.1
Authorization: Bearer [User_100_Token]
Malicious Request (Attempting to Update Victim's Profile):
PUT /api/users/999/profile HTTP/1.1
Authorization: Bearer [User_100_Token]
Impact: If successful, attacker can change victim's email and password, achieving
full account takeover.
Scenario 2: Sensitive Data Leakage via Invoice Access
Normal Request (Accessing Own Invoice):
GET /api/invoices/12345 HTTP/1.1
Cookie: session=abc123xyz
Malicious Request (Accessing Other User's Invoice):
GET /api/invoices/12346 HTTP/1.1
Cookie: session=abc123xyz
Impact: Attacker can iterate through invoice IDs and download sensitive financial
information of all users.
Scenario 3: Password Reset Token Manipulation
Normal Request (Requesting Own Password Reset):
POST /api/auth/reset-password HTTP/1.1
Malicious Request (Requesting Victim's Password Reset):
POST /api/auth/reset-password HTTP/1.1
Impact: If the API accepts the manipulated user_id and trusts the email parameter,
the attacker receives a password reset link for the victim's account.
Conclusion and Key Takeaways
Why BOLA is a Critical Vulnerability
- High Prevalence: One of the most common API vulnerabilities found in the wild
- Severe Impact: Can lead to complete account takeover and massive data breaches
- Easy to Exploit: Requires minimal technical skill once identified
- Difficult to Detect: Automated scanners often miss these vulnerabilities
- Business Logic Dependent: Requires understanding of application context
Essential Testing Checklist
- ✓ Test all HTTP methods (GET, POST, PUT, DELETE, PATCH) on every endpoint
- ✓ Use the OPTIONS method to discover available HTTP methods
- ✓ Replace all user IDs and object IDs with values from your second test account
- ✓ Test with different authentication tokens (JWT, session cookies)
- ✓ Look for hidden parameters in requests that might contain IDs
- ✓ Test both user ID based and object ID based authorization
- ✓ Verify that error messages don't leak sensitive information
- ✓ Check for authorization on read, write, update, and delete operations
- ✓ Test URL paths, query parameters, request bodies, and headers
- ✓ Always use your own test accounts - never test with real user data
Developer Security Checklist
- ✓ Implement centralized authorization mechanisms
- ✓ Extract user identity from authenticated tokens, never from parameters
- ✓ Use UUIDs/GUIDs instead of sequential IDs where possible
- ✓ Verify authorization for every CRUD operation on private objects
- ✓ Implement authorization checks on all HTTP methods
- ✓ Never trust client-supplied user IDs
- ✓ Use role-based access control (RBAC) or attribute-based access control (ABAC)
- ✓ Log all authorization failures for security monitoring
- ✓ Conduct regular security code reviews focusing on authorization logic
- ✓ Perform penetration testing with multiple user contexts
Final Thoughts for Security Researchers
Broken Object Level Authorization represents a goldmine for bug bounty hunters. There are countless
undiscovered BOLA vulnerabilities in production applications today. However, success in finding these
vulnerabilities requires:
- Patience and Thoroughness: Test systematically across all endpoints and methods
- Business Logic Understanding: Take time to understand how the application works
- Ethical Responsibility: Always use your own test accounts and protect user data
- Proper Documentation: Report findings clearly without exposing sensitive
information
- Continuous Learning: Stay updated on new attack vectors and testing techniques
Remember: When you see a user ID in a request, always change it. But make sure you're
changing it to another user ID that belongs to your own test account. This simple principle, when
applied consistently and ethically, can uncover serious security vulnerabilities that protect countless
users from potential attacks.
Stay Secure. Test Ethically. Protect Users.
OWASP API Security - Broken Object Level Authorization Guide