Table of Contents
BBC Ch 24: API Hacking
Source: Bug Bounty Bootcamp by Vickie Li
APIs are the backbone of modern web and mobile apps. They often expose the same backend logic with fewer protections than the main web interface. Many programs explicitly include API endpoints in scope.
API Types
REST – uses HTTP verbs (GET/POST/PUT/DELETE), JSON responses, resource-based URLs (e.g., /users/123).
SOAP – XML-based, uses WSDL to define the service interface, typically POST to a single endpoint.
GraphQL – single endpoint (usually /graphql) with a query language; clients specify exactly what data they need.
API Recon
Finding Documentation
- Check
/api,/api/v1,/swagger,/swagger-ui.html,/openapi.json,/docs - Look for Swagger/OpenAPI spec files (JSON or YAML)
- Search the company's developer portal and GitHub repos for API docs
Proxying Traffic
Route the mobile app or web app through Burp to capture all API calls. This reveals undocumented endpoints and parameter names that aren't in public docs.
Deducing REST Endpoints
REST APIs follow predictable patterns. If you find /users/123, try:
GET /users (list all users?) POST /users (create user?) PUT /users/123 (update user 123?) DELETE /users/123 (delete user 123?) GET /users/123/posts (sub-resource?)
Older API Versions
New versions often have stricter security. Try downgrading:
/api/v2/users/123 -> /api/v1/users/123 -> /api/users/123
GraphQL-Specific Recon
Use introspection to enumerate the entire schema:
POST /graphql
{
"__schema" {
types { name fields { name type { name } } }
}
}
Or list all types:
{ "__schema" { types { name } } }
Tools: InQL (Burp extension), GraphQL Voyager (visualize schema).
Common API Vulnerabilities
Broken Object-Level Authorization (BOLA / IDOR)
The most common API vulnerability. Change object IDs in requests:
GET /api/v1/users/1236/orders -> /api/v1/users/1237/orders GET /api/v1/invoices/9921 -> /api/v1/invoices/9922
Test all HTTP verbs – read access may be restricted but write access may not be:
PUT /api/v1/users/1237 {"email": "attacker@evil.com"}
DELETE /api/v1/users/1237
Broken Function-Level Authorization
Admin endpoints accessible to regular users:
GET /api/v1/admin/users
POST /api/v1/users/1237/promote {"role": "admin"}
Excessive Data Exposure
APIs often return full objects and rely on the client to filter. Check raw API responses for fields not shown in the UI:
GET /api/v1/users/1237
-> {"id": 1237, "email": "...", "ssn": "123-45-6789", "internal_role": "admin"}
Information Disclosure via Error Messages
Send malformed requests and observe errors:
GET /api/v1/users/abc (invalid type -> stack trace?)
POST /api/v1/users {} (missing fields -> field names revealed?)
PUT /api/v1/users/1 {"x":"y"} (unknown field -> accepted or rejected with details?)
Rate Limiting
APIs often lack rate limiting. Test by sending many rapid requests:
for i in $(seq 1 100); do
curl -s -o /dev/null -w "%{http_code}
" "https://api.example.com/users/$i"
done
No 429 responses = no rate limiting. Impact: account enumeration, brute force, mass data harvesting.
Mass Assignment
If the API accepts JSON bodies, try adding privileged fields:
POST /api/v1/users/register
{"username": "attacker", "password": "pass", "role": "admin", "verified": true}
Hunting Methodology
- Map all endpoints via Burp proxy + public docs + deduction from observed patterns
- Try older API versions for each discovered endpoint
- Use GraphQL introspection to enumerate schema if GraphQL is used
- Test every endpoint for IDOR: iterate object IDs across all HTTP verbs
- Check raw API responses for fields not shown in the UI (excessive data exposure)
- Send malformed requests to provoke verbose error messages
- Test rate limiting with rapid sequential requests
- Try mass assignment by adding
role,admin,verified,is_adminfields to POST/PUT bodies
5-Step Checklist
- Enumerate all API endpoints via proxying, docs, deduction, and older version paths.
- Run GraphQL introspection if applicable; map the full schema.
- Test every object-referencing endpoint for IDOR by changing IDs and using all HTTP verbs.
- Check raw API responses for data not rendered in the UI; probe with malformed requests for verbose errors.
- Test rate limiting and mass assignment; document concrete impact (data read, privilege gained) before reporting.
