API Enumeration

APIs Are Everywhere

Modern web applications don’t just serve HTML pages. Behind the UI, there’s usually a set of APIs (Application Programming Interfaces) that handle the actual logic: authentication, data retrieval, user management, file operations.

These APIs are often less protected than the web UI. The frontend might enforce input validation and access controls, but the API behind it might not.

If the frontend says “you can’t do that,” the API might disagree.


REST API Basics

Most web APIs follow the REST (Representational State Transfer) pattern.

Key characteristics:

  • Endpoints are URLs that represent resources: /api/users, /api/books
  • HTTP methods define the action: GET (read), POST (create), PUT (update), DELETE (remove)
  • Data is usually JSON: {"username": "admin", "password": "secret"}
  • Versioned paths: /api/v1/users, /api/v2/users

The API Path Convention

API paths are usually predictable:

/api/version/resource

For example:

  • /api/v1/users - list all users
  • /api/v1/users/admin - specific user
  • /api/v1/users/admin/password - specific property
  • /api/v2/books/search - search functionality

Predictable naming is your advantage. If you find /api/v1/users, you can guess that /api/v1/books and /api/v1/admin probably exist too.


Discovering APIs with Gobuster

You can’t test APIs you haven’t found. Gobuster has a powerful pattern feature for API discovery.


Creating a Pattern File

APIs are versioned. Create a pattern file that appends version numbers to every wordlist entry:

echo '{GOBUSTER}/v1' > pattern.txt
echo '{GOBUSTER}/v2' >> pattern.txt

The {GOBUSTER} placeholder gets replaced with each word from the wordlist.


Running the Scan

gobuster dir -u http://10.10.10.50:5001 -w /usr/share/wordlists/dirb/big.txt -p pattern.txt

This might discover:

  • /api/v1/books (Status: 200)
  • /api/v1/users (Status: 200)
  • /console (Status: 200)

Each of these is a thread to pull.


Interacting with APIs using curl

curl is your command-line API client. It’s on every system and gives you full control over HTTP requests.


Basic GET Request

curl -i http://10.10.10.50:5002/api/v1/users

The -i flag includes response headers, which reveal server software, content types, and more.


POST Request with JSON

curl -d '{"username":"admin","password":"test"}' 
  -H 'Content-Type: application/json' 
  http://10.10.10.50:5002/api/v1/users/login
  • -d sends data in the request body
  • -H sets a header (here, telling the server we’re sending JSON)

Changing the HTTP Method

curl -X PUT 
  -H 'Content-Type: application/json' 
  -H 'Authorization: Bearer eyJ...' 
  -d '{"password":"pwned"}' 
  http://10.10.10.50:5002/api/v1/users/admin/password

The -X flag overrides the default method (GET) with any method you want.


HTTP Methods Matter

The same endpoint can behave completely differently depending on the HTTP method you use.


What Each Method Does

MethodPurposeWhen to try it
GETRead dataAlways, it’s the default
POSTCreate something newLogin forms, registration, uploads
PUTReplace/update existing dataChanging passwords, updating profiles
PATCHPartial updateSame as PUT but for single fields
DELETERemove somethingAccount deletion, file removal

Reading Error Messages

Error responses tell you more than you think:

ResponseWhat it really means
404 Not FoundEndpoint doesn’t exist
405 Method Not AllowedEndpoint exists, wrong method
401 UnauthorizedEndpoint exists, need credentials
403 ForbiddenEndpoint exists, insufficient privileges
400 Bad RequestEndpoint exists, wrong parameters

A 405 is better than a 404. It confirms the endpoint is real. Try a different method.


The API Exploitation Chain

Finding one endpoint leads to finding more. Each discovery feeds the next step.


A Real Attack Flow

Here’s how API enumeration leads to full compromise:

  1. Brute-force API paths with Gobuster patterns → find /api/v1/users
  2. GET /api/v1/users → returns a list of usernames including “admin”
  3. Brute-force /api/v1/users/admin/ → discover /email and /password sub-paths
  4. POST to /login with wrong password → error says “Password is not correct” (confirms the username is valid)
  5. POST to /register with "admin": true in the JSON → creates an admin account
  6. Login with new account → get a JWT token
  7. PUT to /api/v1/users/admin/password with the JWT → change the real admin’s password

Full admin takeover, no exploit code needed. Just curl and creative enumeration.


JWT Tokens

Many APIs use JSON Web Tokens (JWT) for authentication. After a successful login, the server returns a token. You include it in subsequent requests:

curl -H 'Authorization: Bearer eyJhbGciOiJ...' 
  http://10.10.10.50:5002/api/v1/users/admin

JWTs are base64-encoded and have three parts separated by dots. You can decode them to see the payload:

echo 'eyJhbGciOiJ...' | base64 -d

This reveals the username, role, and expiration. Sometimes the role can be tampered with if the server doesn’t validate the signature properly.


Common API Vulnerabilities

VulnerabilityWhat to look for
Broken access controlCan you access other users’ data by changing the ID?
Mass assignmentDoes the registration endpoint accept "admin": true?
Excessive data exposureDoes the API return more fields than the UI shows?
Missing rate limitingCan you brute-force the login endpoint?
Method confusionDoes PUT work where POST is rejected?
Verbose errorsDo error messages reveal valid usernames or internal paths?

APIs trust the client more than they should. The frontend may enforce rules, but the API often doesn’t. Always test the API directly with curl or Burp, bypassing the UI entirely.


Practice Boxes

  • Nibbles - Web enumeration leading to CMS admin exploitation
  • Bashed - Directory brute-forcing reveals a hidden web shell
  • Pickle Rick - Source code inspection and command injection
  • Blunder - Web app enumeration and CMS exploitation