API Reconnaissance
Discovering API endpoints, parameters, authentication schemes, and data structures. Swagger/OpenAPI docs, GraphQL introspection, directory brute-force, response fingerprinting — the recon toolkit for API testing.
Discovering API endpoints, parameters, authentication schemes, and data structures. Swagger/OpenAPI docs, GraphQL introspection, directory brute-force, response fingerprinting — the recon toolkit for API testing.
Before an attacker can exploit an API, they must understand its surface area. API reconnaissance is the process of discovering endpoints, mapping parameters, identifying authentication schemes, and fingerprinting the technology stack. Every undocumented endpoint, every disabled introspection query, and every verbose error message is a gift to an attacker.
API reconnaissance is an information-gathering phase that happens before any exploit is attempted. It answers four questions: what endpoints exist, what parameters do they accept, what authentication do they require, and what technology runs behind them. The depth of reconnaissance available depends on how much the API reveals about itself.
Many APIs expose documentation at predictable paths: /api/docs, /swagger.json, /openapi.json. An OpenAPI spec lists every endpoint, its HTTP method, query parameters, request body schema, and response structure. This is the single most valuable file an attacker can find - it is a complete map of the API surface, often including internal or deprecated endpoints that should never have been documented.
GraphQL APIs expose a single endpoint (usually /graphql) but the entire schema is available through introspection. Sending the __schema meta-query returns every type, field, argument, mutation, and subscription. This includes fields marked as deprecated, internal, or experimental. Many production GraphQL APIs disable introspection, but a surprising number leave it enabled.
# Introspection query — returns the entire schema
query {
__schema {
types {
name
fields {
name
type { name }
description
isDeprecated
}
}
}
}
# Common dangerous fields found via introspection:
# user(id: ID!, resetToken: String) — password reset
# creditCard(last4: String) — payment data
# internalNotes — private data
# __internalSchema — hidden operationsWhen documentation is not available, attackers use wordlist-based brute-force tools (like ffuf, gobuster, or dirb) to discover endpoints. A tool sends thousands of requests with paths from a wordlist and flags any that return a non-404 response. Common discoveries include /admin, /internal, /debug, /v2, and /.env.
Response fingerprinting uses HTTP headers and error messages to identify the technology stack. A X-Powered-By: Express header, a Server: gunicorn header, or a Python stack trace in an error response all reveal backend technology. This information guides the attacker toward framework-specific exploits.
Use the reconnaissance tool below to enumerate endpoints, run GraphQL introspection, and fuzz parameters. Each tab simulates a real recon technique against a mock API.
No scan data
Click "Discover" to scan the API surface.
In September 2018, Facebook disclosed a vulnerability that affected 50 million user accounts. The bug was discovered through API reconnaissance - specifically, endpoint enumeration and parameter fuzzing of Facebook's GraphQL API. The feature in question was "View As", which let users see their own profile as it appeared to a specific friend.
The "View As" feature generated a video upload interface that included a Happy Birthday greeting. The vulnerability was triggered by a combination of three separate issues: (1) an API endpoint that accepted a user ID parameter without validating the relationship, (2) a parameter fuzzing opportunity in the video upload flow that accepted unexpected input, and (3) the generated access token was scoped to the wrong user. An attacker who discovered this combination could steal access tokens and take over any Facebook account.
The Facebook case demonstrates a key principle: API recon is rarely about finding a single smoking-gun endpoint. It is about chaining together small discoveries - an undocumented parameter here, a missing validation there, a verbose error message over there - to build a working exploit. Each piece of information gathered during recon contributes to the attacker's understanding of the API's hidden behaviour.
Every piece of information an API reveals during recon makes the attacker's job easier. Mitigation focuses on minimising what the API exposes before authentication:
// VULNERABLE — exposed documentation and introspection
app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec));
// VULNERABLE — GraphQL introspection enabled in production
const server = new ApolloServer({ schema, introspection: true });
// VULNERABLE — verbose error messages leak stack traces
app.use((err, req, res, next) => {
res.status(500).json({ error: err.stack }); // stack trace leaked
});
// SAFE — disable docs and introspection in production
const isProd = process.env.NODE_ENV === 'production';
if (isProd) app.use('/api/docs', (req, res) => res.status(404).end());
const server = new ApolloServer({
schema,
introspection: !isProd,
});
// SAFE — generic error responses
app.use((err, req, res, next) => {
res.status(500).json({ error: 'Internal server error' });
});
// SAFE — remove fingerprinting headers
app.disable('x-powered-by');
app.use((req, res, next) => {
res.removeHeader('Server');
next();
});Additional defences include: returning 404 instead of 403 for unauthorised access to hidden endpoints (so the attacker cannot distinguish between "exists but forbidden" and "does not exist"), using consistent error formats that do not reveal the technology stack, disabling directory listing on all servers, and implementing API discovery monitoring that alerts when a client requests many non-existent paths (a sign of directory brute-force).
1.What is the most valuable piece of information an attacker can find during API reconnaissance?
2.Why should production GraphQL APIs disable introspection?
3.Why is it better to return a 404 status code instead of 403 for unauthorised access to a hidden endpoint?