Here are some steps for enumerating an API.
What/where is the API?
- Scan server ports. Is it a REST API, gRPC, GraphQL, etc?
- Look for
/api
path if web server is HTTP. - Look for an API subdomain, e.g.
api.example.com
.
What are its endpoints?
- Look for API endpoints referenced in client (take a look at frontend HTML/JS or reverse engineer client binary).
- Look for API schemas. Does the
/api/
route provide anything? - Is the documentation endpoint exposed? Does it provide request & reply schemas? As a side note, if an API uses some kind of Swagger/OpenAPI UI library, look for related vulnerabilies.
/swagger/index.html
/openapi.json
- Are there multiple versions of the API in production? Try to see if older APIs are vulnerable.
/api/v1
: basic URL versioning/api/<some-endpoint>/v1
: per-route versioning- Versioning via HTTP header, e.g.
X-Api-Version
- Try to register as a user, use various site functionalities, and use Burp Suite to record & map out all the routes.
- Try dirbust for API endpoints recursively (perhaps using OPTIONS if supported). You might have to make your own wordlist that suits the context of the API/service/company.
For each endpoint:
- What are the parameters? Can you bruteforce for more hidden parameters? Can you try injecting key-values pairs (e.g.,
isAdmin=true
that may be accidentally bound to server-side objects?- Is the server validating the values properly (type, range, format, etc)?
- Are there conflicts between optional parameters? Does the server check them properly?
- Are there subresources? e.g.
/api/users/:user-id/paymentmethods
- What are the allowed methods? Try
OPTIONS
or just try all methods one by one. - What kind of formats does it accept? JSON? url-form-encoded? Media (.mp4, .jpeg, etc)? Can you fiddle with the parsing process?
- Does it use gzip compression? Can you crash the server with a gzip bomb?
- Does API server have per-IP or per-user rate-limiting? Does it throttle properly?
- Does the API authenticate via header (e.g. JWT) or session cookie? Does the server check for authorization properly? Try accessing the resource as a different identity.
- Try messing with the
Content-Type
with and without changing the actual content. Does it trigger any error? Can this bypass schema (e.g., JSON schemas) checks? Does finding a new accepted format open up injection possibilities?