VAmPI Vulnerable API: A Beginner's Guide to API Security Testing

VAmPI Vulnerable API: A Beginner's Guide to API Security Testing


In this post, I’m walking through my hands-on experience exploring VAmPI, a deliberately vulnerable API designed to simulate real-world security issues based on the OWASP Top 10 for APIs. This project was a learning exercise intended to deepen my understanding of how APIs work, how they can break, and how attackers might exploit them.

VAmPI is a great sandbox for anyone interested in API security. It’s lightweight, self-contained in Docker, and includes common vulnerabilities you’d find in production APIs.


Objectives

The primary goal of this walkthrough was to build a practical foundation in API security testing by working through real vulnerabilities in a controlled environment. Specifically, I aimed to:

  • Gain hands-on experience with common API vulnerabilities outlined in the OWASP API Top 10, including issues like Broken Object Level Authorization, Mass Assignment, and JWT misconfigurations.
  • Deploy and configure the VAmPI testing environment locally using Docker, simulating a real-world API deployment scenario.
  • Leverage industry-standard tools — including Postman, Burp Suite, ffuf, sqlmap, and Python — to interact with, probe, and exploit the API just as a professional security tester or attacker would.
  • Thoroughly document each vulnerability discovered, along with the testing process, to strengthen both technical understanding and reporting skills from a security assessment perspective.


What Is an API and Why Does It Matter?

An API (Application Programming Interface) is a set of rules and protocols that allows different software systems to communicate with each other. Think of it as a bridge that lets one application request and exchange data or functionality from another system — whether that’s a database, a service, or another application.

For example, when you log in to a website using your Google account, you’re interacting with Google’s API. The site sends your request, and Google’s API responds with your credentials, profile info, or token, depending on what’s being asked.

Article content

Why APIs Matter in Cybersecurity

APIs are everywhere — from mobile apps and web services to IoT devices and enterprise platforms. Because they often expose sensitive functions and data, they’ve become a prime target for attackers.

Some reasons APIs are critical in cybersecurity:

  • They handle authentication, authorization, and data flow — core security responsibilities.
  • Misconfigured or poorly coded APIs can leak data or expose critical functions.
  • API endpoints are often public-facing, making them accessible to anyone on the internet.
  • Modern attacks increasingly target APIs, especially as web apps shift toward frontend-heavy architectures (e.g., single-page apps using RESTful backends).

Understanding how to secure APIs is no longer optional — it’s foundational to securing any modern digital environment.


Phase 1: Setting Up VAmPI

Installing Docker and Running the Container

To get started, I launched the VAmPI API using Docker. Here’s the command I used:

sudo docker run -d -e vulnerable=1 -e tokentimetolive=18000 -p 5000:5000 erev0s/vampi:latest        

This launched the API in vulnerable mode, extended the JWT token lifetime to five hours, and exposed the service on port 5000.

I confirmed the API was running with:

curl http://localhost:5000        
Article content
BaseURL Confirmed and Curl Confirmed

And received a valid JSON response confirming that VAmPI was live and ready to test.


Phase 2: Reconnaissance and Enumeration

Before jumping into testing for vulnerabilities, I began with reconnaissance — the process of discovering what the API exposes to the outside world. This phase is critical for any black-box testing scenario, especially when you don’t have access to the source code or backend infrastructure. In API pentesting, enumeration helps identify which endpoints exist, what data they expose, and how they might be vulnerable to misuse.

Nmap Scanning: Identifying Open Ports and Services

I used Nmap, a widely-used network scanner, to probe the local machine and detect any running services or open ports.

sudo nmap -sC -sV -O -p- localhost        

Flags explained:

  • -sC: Runs Nmap’s default scripts for service detection.
  • -sV: Attempts to identify service versions.
  • -O: Tries to determine the operating system of the target.
  • -p-: Scans all 65535 TCP ports, not just the top 1000.

Why this matters: APIs typically run over HTTP or HTTPS, but they could also be exposing other ports (e.g., for databases or debug interfaces). I wanted to be thorough and rule out any unexpected services running on the system.

Results:

  • Port 5000/tcp was open and serving the API via Werkzeug, a Python WSGI server.
  • This confirmed that VAmPI was running and accessible on port 5000, which became the focus for the rest of the testing.

Article content
Nmap Results


Directory Discovery with ffuf: Finding Hidden or Undocumented Endpoints

Once I confirmed that the API was accessible, I used ffuf (a fast web fuzzer) to brute-force possible endpoint paths. Since APIs don’t always expose a UI or documentation (like Swagger), this method helps enumerate hidden or undocumented routes.

ffuf -u http://localhost:5000/FUZZ -w ~/Desktop/VAmPI/api-directory-lists-custom.txt -mc 200,401,403        

Command breakdown:

  • -u http://localhost:5000/FUZZ: The FUZZ keyword is a placeholder ffuf replaces with each word in the wordlist.
  • -w: Specifies the custom wordlist containing potential endpoint names.
  • -mc 200,401,403: Only shows results with these HTTP status codes, which indicate valid or restricted endpoints.

Why this matters: Many vulnerable or test APIs have routes that aren’t obvious or publicly documented. Using a wordlist that includes RESTful patterns (/login, /register, /users/v1, etc.) increases the chances of discovering such endpoints.

Article content
ffuf Results

Endpoints discovered:

  • /users/v1: Base endpoint for user-related actions
  • /books/v1: Base endpoint for books and secrets
  • /users/v1/_debug: A developer debug route that ended up exposing full user data
  • /createdb: Re-initializes the database (including test users)
  • /me: Returns data for the currently authenticated user
  • /users/v1/register: Endpoint for creating new accounts
  • /users/v1/login: Authenticates a user and returns a JWT

Each of these became a lead for potential misconfigurations, data exposure, or insecure logic. The next step was to load these into Postman to begin exploring how the API functioned and where security controls could be bypassed.


Phase 3: Interacting with the API via Postman

After identifying VAmPI’s accessible endpoints during the enumeration phase, the next step was to interact with the API using Postman. Postman is an incredibly useful tool for working with RESTful APIs. It allows for clean request building, token management, and testing workflows — all without needing to write scripts.

Article content
Postman VAmPI

This phase is about building a baseline understanding of the API’s logic and behavior — how authentication works, what requests are valid, and how the application responds to edge cases.

Importing the API Specification

VAmPI provides an OpenAPI 3.0 specification (openapi3.yml) via its GitHub repository. I used this to generate a structured collection of API calls in Postman.

Steps I followed:

  1. Opened the openapi3.yml file in Swagger Editor.
  2. Exported the spec as a Postman Collection (JSON).
  3. Imported it into Postman.
  4. Set the baseURL variable to match my local setup:

http://localhost:5000        
Article content
List of Endpoints

This immediately gave me a full list of endpoints, grouped by resource (users, books, etc.), making it easy to start testing systematically.

Step 1: Seeding the Database

Before diving into functionality, I initialized VAmPI’s database using the /createdb endpoint:

GET /createdb        

This populated the system with default users, books, and admin accounts, which were critical for the exploitation steps that followed.

Article content
/createdb

Step 2: Registering a New User

Next, I used the /users/v1/register endpoint to create my own user account:

{
  "username": "edward",
  "email": "edward@vampi.local",
  "password": "hunter2"
}        

The API responded with a 201 Created, confirming that the user was successfully registered.

Article content
/register

Step 3: Logging In and Capturing a JWT

I then logged in using the /users/v1/login endpoint:t

{
  "username": "edward",
  "password": "hunter2"
}        

The response included a JSON Web Token (JWT):

{
  "token": "<jwt_token_here>"
}        
Article content
/login

This token is critical — it is used to authorize future requests by adding it to the Authorization header:

Authorization: Bearer <jwt_token>        

In Postman, I stored this token as an environment variable and set up the Authorization tab to use the Bearer Token type. This allowed me to reuse the token automatically across all authenticated requests.

Step 4: Exploring Authenticated Endpoints

With the token set, I was now able to explore protected endpoints:

  • GET /me returned the profile of the currently authenticated user.
  • GET /users/v1/_debug exposed a full dump of all users in the system, including plaintext passwords and admin flags.

This last discovery was alarming — and it confirmed the presence of Excessive Data Exposure. The endpoint was likely left in place for internal testing and never removed from the deployed version.

Article content
/_debug

Step 5: Reviewing the API’s Behavior

During this exploration phase, I observed several things that hinted at deeper vulnerabilities:

  • The API accepted full JSON payloads, even with unexpected fields.
  • There were no visible access control checks beyond the token — this would become relevant in later tests.
  • Error messages and status codes were consistent, making enumeration easier later on.

At this point, I had a working test environment, an authenticated user, and access to sensitive internal data. The next step was to test the API for logic flaws and security misconfigurations — and that’s exactly what I did in the exploitation phase.


Phase 4: Vulnerability Testing

With a working understanding of the API’s structure and authentication in place, I started actively probing for vulnerabilities. I focused on the OWASP API Top 10 list and used both manual testing and automation tools to identify weak points in VAmPI’s logic, data handling, and authorization controls.

This phase involved crafting requests, altering payloads, and switching tokens — essentially looking for cracks in the API’s assumptions about how it should be used.

1. Excessive Data Exposure — OWASP API #3 — Excessive Data Exposure

Endpoint Tested:

GET /users/v1/_debug        

Observation: This endpoint returned a full dump of user data, including:

  • username
  • email
  • password (in plaintext)
  • admin status (true/false)

Article content
Full Data Dump

Why It’s a Problem: This kind of debug endpoint is often left in accidentally after development. In this case, it completely bypassed access control, leaking sensitive information to any authenticated user. It exposed not only personally identifiable information (PII), but also credentials that could be used in other parts of the application.

2. Mass Assignment — OWASP API #6 — Mass Assignment

Test Case: During user registration at:

POST /users/v1/register        

I added an extra field that shouldn’t be user-controllable

{
  "username": "eviladmin",
  "email": "evil@vampi.local",
  "password": "rootkit123",
  "admin": true
}        

Result: The server accepted the payload and created a new user with administrative privileges. There were no safeguards preventing the assignment of sensitive fields like admin.

Article content
/register

Why It’s a Problem: The API blindly trusted all fields in the incoming JSON body without whitelisting or filtering. This allowed me to modify internal application state and escalate privileges — a classic Mass Assignment vulnerability.

3. Broken Object Level Authorization (BOLA) — OWASP API #1 — Broken Object Level Authorization

Setup: I created a book entry as edward:

{
  "book_title": "BOLA Test",
  "secret": "This is my secret book"
}        
Article content
Create book

Then I logged in as a different user and accessed:

GET /books/v1/BOLA%20Test        

Result: I was able to read the secret field for a book I didn’t create.

Article content
Get secret Book

Why It’s a Problem: The API didn’t verify ownership of the resource being requested. Even though the data was tied to a specific user, any authenticated token could access it by simply guessing or scanning book titles.

4. Unauthorized Password Change — OWASP API #5 — Broken Function Level Authorization

Test: Using another user’s JWT (e.g. sam), I attempted to change the password for edward:

PUT /users/v1/edward/password        
{
  "password": "newpass123"
}        

Result: The request succeeded. There were no access checks ensuring that only the rightful user could update their own credentials.

Article content
Changed Password

Why It’s a Problem: This exposes every user to account takeover. All that’s needed is a valid JWT — not even an admin token. A malicious user could rotate passwords for all accounts and lock others out.

5. SQL Injection — OWASP API #8 — Injection

Target Endpoint:

GET /users/v1/{username}        

Process: I proxied the request through Burp Suite and ran a simple payload test:

GET /users/v1/sam' OR '1'='1        
Article content
Intruder Results

The server responded with a 500 Internal Server Error, suggesting backend SQL processing without proper sanitization.

Follow-Up with sqlmap:

sqlmap -u "http://localhost:5000/users/v1/*edward*" \
--method=GET \
--headers="Authorization: Bearer <jwt>" --dump        

Result:

  • Retrieved user table (IDs, emails, usernames, passwords, admin status)
  • Retrieved books table (titles, secrets, user IDs)

Article content
Database Dump

Why It’s a Problem: SQL Injection allows full control over the backend database. In this case, I was able to dump the entire schema and contents of the database with almost no resistance.

At this point in the walkthrough, I had already uncovered several critical vulnerabilities — all without advanced exploitation techniques. Most issues stemmed from missing access controls, insecure design assumptions, or lack of input validation.


Phase 5: Authentication Bypass and Rate Limiting

At this point in the project, I turned my focus to two specific areas that are critical in API security: authentication mechanisms (particularly how JWTs are validated) and the presence (or lack) of rate limiting on login attempts.

These kinds of issues are at the core of the OWASP API Top 10 and often lead to full account compromise if left unaddressed.

Article content
JWT

JWT Authentication Bypass

VAmPI uses JWTs (JSON Web Tokens) to manage user authentication. When a user logs in, the API returns a token that includes key details such as:

  • sub: The subject (i.e. username or user ID)
  • iat: Issued at timestamp
  • exp: Expiry time

The token is signed using the HS256 algorithm, which relies on a shared secret key between the client and server.

JWTs are formatted like this:

<base64-encoded header>.<base64-encoded payload>.<signature>        

After decoding a valid token using fusionauth.io/dev-tools/jwt-decoder, I confirmed the following header structure:

{
  "alg": "HS256",
  "typ": "JWT"
}        
Article content
Decoded JWT

This indicated the use of symmetric (shared-secret) signing. If the secret key was weak or guessable, I could potentially forge a valid token and impersonate any user — including an admin.


Forging a Token as eviladmin

Using Python and the PyJWT library, I wrote a simple script to generate a forged token. I assumed "secret" as the signing key — a common (and insecure) default used in development environments.

import jwt, time

payload = {
    "sub": "eviladmin",
    "iat": int(time.time()),
    "exp": int(time.time()) + 3600
}
token = jwt.encode(payload, "secret", algorithm="HS256")
print(token)        
Article content
Token Created

I then copied the token and added it to the Authorization header in Postman:

Authorization: Bearer <forged_token>        

Testing Forged Token Access — OWASP API #2 — Broken Authentication

Using this forged token, I accessed:

  • GET /me → returned the profile for eviladmin
  • GET /users/v1/_debug → exposed the full user database

These endpoints responded successfully, even though I had never logged in as eviladmin. The API fully accepted my self-signed token without verifying its legitimacy beyond the signature.

Article content
Succesful Broken Authentication

Vulnerability Confirmed: The JWT implementation was insecure due to a weak secret key and insufficient validation of token contents.


Conclusion

This project gave me a practical, in-depth look into API security testing by working hands-on with the VAmPI vulnerable API. What started as a basic exploration into how RESTful APIs are structured quickly evolved into uncovering multiple high-impact vulnerabilities — many of which reflect issues found in real-world systems.

Through this walkthrough, I was able to:

  • Enumerate API endpoints using nmap and ffuf
  • Understand and interact with authentication flows via JWTs
  • Identify and exploit logic flaws like mass assignment and BOLA
  • Perform SQL injection to extract sensitive backend data
  • Forge authentication tokens due to weak cryptographic implementation
  • Begin planning a brute-force attack to highlight the absence of rate limiting

Each step helped reinforce not only how APIs are built and consumed, but also how attackers approach these systems when security is misconfigured or incomplete.

What stood out most is that none of these vulnerabilities required advanced tools or obscure techniques. They all came down to either weak assumptions by the developers or missing security controls that should be foundational to any API-based service.

Why This Matters

APIs are everywhere — from mobile apps to cloud services — and they’re increasingly the primary interface for users, data, and business logic. With that increased exposure comes increased risk. If API security isn’t treated as a first-class priority, attackers can abuse endpoints, escalate privileges, or gain access to entire systems just by sending the right HTTP request.

VAmPI was a perfect environment to explore these weaknesses safely and systematically. It allowed me to practice the OWASP API Top 10 in a controlled setting while building the skills I’ll need to audit or assess real-world APIs moving forward.


#APIsecurity #OWASPTop10 #VAmPI #BugBounty #PenetrationTesting #Cybersecurity #WebAppSecurity #JWT #SQLInjection #BurpSuite #Postman #Docker #EthicalHacking #RedTeam #BugHunting #CTF #PythonSecurity #ffuf #sqlmap #InfoSec #APIhacking #InfosecCommunity #CyberSecLabs #APIPentest #SecurityTesting #OffensiveSecurity #DevSecOps

Nelson Cacuango

💻 Cybersecurity Learner / ⚔️ eJPTv2 / 🛡️CWL BTF

3w

Thanks for sharing, awesome and detailed article. 🧑💻🙌

To view or add a comment, sign in

More articles by Jose Pacheco

Insights from the community

Others also viewed

Explore topics