Modern API Hacking: A Methodology for Hunting BOLA Vulnerabilities

Imagine you're auditing a brand-new fintech application. You've mapped the attack surface, enumerated subdomains, and found the primary API serving the mobile app. You intercept a request to fetch your own account balance: GET /api/v2/accounts/849201. You change the ID to 849202, hit forward, and suddenly you are looking at the financial history of a complete stranger.
No complex memory corruption. No zero-days. Just a missing if statement on the backend.
Welcome to Broken Object Level Authorization (BOLA)—historically known as Insecure Direct Object Reference (IDOR). BOLA remains the undisputed king of API vulnerabilities, consistently ranking as the number one threat in the OWASP API Security Top 10.
Today, we are laying down a concrete, stage-by-stage methodology for hunting BOLA vulnerabilities in modern REST and GraphQL APIs.
As always, this methodology is strictly intended for authorized bug bounty hunting, penetration testing, and defensive engineering. Never modify object IDs on targets without explicit permission.
Stage 1: The Goal and Scope Rules
Before firing up Burp Suite or Caido, define your goal. The objective of BOLA hunting is to prove that User A can access, modify, or delete an object belonging to User B without proper authorization.
The golden rule of BOLA testing: Always test with two distinct, authorized accounts controlled by you. If you only have one account and you blindly iterate IDs, you risk accessing real customer data (a severe scope violation) or modifying production state. Create User_Attacker and User_Victim.
Stage 2: Endpoint Enumeration and Mapping
You cannot exploit what you cannot see. BOLA vulnerabilities often hide in deprecated or unlinked endpoints. Your first task is to build a comprehensive map of the API.
- Passive Mapping: Proxy your traffic through Burp Suite while clicking every single button in the web and mobile application.
- Active Discovery: Use tools like Kiterunner to discover hidden API routes. Kiterunner excels here because it understands API path structures (e.g.,
/api/v1/users/{id}) better than standard directory brute-forcers.
# Example: Using Kiterunner to discover hidden API endpoints # This uses the Assetnote wordlists specifically compiled for API routes. kr scan https://api.example.com -w routes-large.kite -A=apiroutes-210228
Look for any endpoint that takes an identifier:
- User IDs (
/users/1234) - Document IDs (
/docs/uuid-string) - Numeric parameters (
?invoice_id=998)
Stage 3: The Testing Workflow
Once you have identified a target endpoint, the testing phase begins.
1. Baseline the Request
First, verify that the endpoint works correctly for User_Attacker.
GET /api/v2/messages/5551 HTTP/2 Host: api.example.com Authorization: Bearer <Attacker_Token> # Response: 200 OK {"id": 5551, "body": "Hello Attacker!"}
2. The Direct ID Swap
Swap the ID 5551 (owned by the attacker) with 5552 (owned by User_Victim). Leave the Authorization header as <Attacker_Token>.
GET /api/v2/messages/5552 HTTP/2 Host: api.example.com Authorization: Bearer <Attacker_Token>
If the server returns a 200 OK with the victim's data, you have found a BOLA. If it returns a 401 Unauthorized or 403 Forbidden, the basic authorization check is working. But we don't stop there.
An architectural overview of a BOLA attack: The API gateway authenticates the user, but the backend microservice fails to verify if the authenticated user actually owns the requested database record.
3. Bypassing Basic Defenses (Parameter Pollution)
Developers often write flawed authorization middleware. If GET /api/v2/messages/5552 is blocked, try HTTP Parameter Pollution (HPP). Provide two IDs in the query string or JSON body. The authorization middleware might check the first ID (which you own), while the backend database query processes the second ID (the victim's).
// Example: JSON Parameter Pollution to bypass BOLA checks { "message_id": 5551, "message_id": 5552 }
4. The UUID Fallacy
A common developer mistake is assuming that because an ID is a UUID (e.g., 123e4567-e89b-12d3-a456-426614174000), it cannot be guessed, and therefore authorization checks are unnecessary. This is Security by Obscurity.
If the app uses UUIDs, look for "leakage endpoints". Can you find the victim's UUID by searching for their username? Does the /api/v1/users/search endpoint return the UUIDs of all users? If you can leak the victim's UUID, you can plug it into the vulnerable endpoint.
Common Mistakes Hunters Make
- Ignoring HTTP Methods: A developer might secure
GET /api/v1/users/{id}but completely forget to securePUT /api/v1/users/{id}orDELETE /api/v1/users/{id}. Always test all REST verbs. - Testing only Numeric IDs: As mentioned above, assuming UUIDs are secure. Always attempt to leak UUIDs and test them.
- Missing the "Mass Assignment" combo: Sometimes you can combine BOLA with Mass Assignment. For example, updating your own user profile (
PUT /api/v1/users/me) by appending{"role": "admin"}.
How Defenders Catch This
If you are on the blue team, defending against BOLA is notoriously difficult because the malicious request looks identical to a legitimate request. A Web Application Firewall (WAF) cannot easily tell if User A is allowed to access Resource B, because that relationship only exists in the database.
To detect this, defenders must implement Zero Trust architecture at the code level. Every single database query that fetches a resource based on user input must include a WHERE owner_id = current_user_id clause.
# Vulnerable Code Pattern (Django/Python) # The developer fetches the record based purely on the ID provided in the URL def get_invoice(request, invoice_id): invoice = Invoice.objects.get(id=invoice_id) # VULNERABLE TO BOLA return JsonResponse(invoice.data) # Safe Fixed Version # The database query explicitly enforces ownership def get_invoice_safe(request, invoice_id): # Safe: Filters by both the invoice ID AND the authenticated user invoice = get_object_or_404(Invoice, id=invoice_id, owner=request.user) return JsonResponse(invoice.data)
At the infrastructure level, defenders are increasingly using specialized API security tools (like Noname Security or Traceable) that build baseline behavioral models of which users access which endpoints, flagging sudden spikes in 403 Forbidden errors (indicating an attacker iterating IDs) or anomalous cross-tenant access.
The Takeaway
BOLA remains rampant because it represents a fundamental failure in business logic, not a cryptographic flaw that a library can automatically fix. As long as developers continue to trust client-provided IDs without verifying server-side ownership, API hacking will remain an incredibly lucrative field for bug bounty hunters.
Related Blogs
- Tool Roundup: The Best Secrets Scanners for CI/CD Pipelines
- Mastering Cloud Reconnaissance: A Methodology for AWS & Azure Penetration Testing
- The Silent Compromise: Analyzing Zero-Click Media Exploits in Android 16
References / Further Reading
- OWASP API Security Top 10 (2023). https://owasp.org/API-Security/editions/2023/en/0x11-t10/
- Assetnote Kiterunner Repository (GitHub). https://github.com/assetnote/kiterunner
- "A Bug Hunter's Guide to BOLA" (PortSwigger Web Security Academy). https://portswigger.net/web-security/access-control/idor
- "API Security Testing Methodology" (HackTricks). https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/api-pentesting


