Graphql Introspection with Basic Auth
How Graphql Introspection Manifests in Basic Auth
GraphQL introspection is a powerful feature that allows clients to query an API's schema to discover available types, queries, and mutations. When combined with Basic Authentication, this creates a dangerous attack surface where an attacker with stolen credentials can enumerate your entire API structure.
Basic Auth credentials are often stored in configuration files, environment variables, or browser storage. Once obtained, an attacker can use these credentials to access the GraphQL endpoint and run introspection queries. The vulnerability manifests when APIs expose introspection endpoints without proper authentication checks or when the Basic Auth implementation doesn't restrict access to sensitive GraphQL operations.
Consider this common scenario: a developer sets up Basic Auth for their GraphQL API but forgets to disable introspection in production. An attacker who obtains credentials through credential stuffing, phishing, or exposed configuration files can then run queries like:
POST /graphql HTTP/1.1
Authorization: Basic Zm9vOmJhcg==
{
"query": "{\n __schema {\n queryType { name }\n mutationType { name }\n types {\n name\n description\n }\n }\n }"
}
Even more concerning is when APIs implement Basic Auth but fail to validate permissions for GraphQL operations. An attacker might have read-only credentials but can still run introspection queries that reveal sensitive field names, database structures, and business logic that could be exploited in subsequent attacks.
The problem compounds when APIs use GraphQL subscriptions with Basic Auth. An attacker can subscribe to real-time data streams using stolen credentials and run introspection queries to understand the data flow patterns, potentially discovering timing-based vulnerabilities or data correlation opportunities.
Basic Auth-Specific Detection
Detecting GraphQL introspection vulnerabilities in Basic Auth contexts requires a multi-layered approach. Start by examining your authentication middleware to ensure it properly validates credentials before allowing any GraphQL operations.
Look for these specific patterns in your code:
// Vulnerable: Basic Auth check only on endpoint, not on GraphQL operations
app.use('/graphql', basicAuth({ users: { 'admin': 'password' } }));
// Better: Validate credentials within GraphQL context
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const credentials = basicAuth(req);
if (!credentials || credentials.name !== 'admin' || credentials.pass !== 'password') {
throw new AuthenticationError('Invalid credentials');
}
return { user: credentials.name };
}
});
Automated scanning tools like middleBrick can detect this specific vulnerability by testing your GraphQL endpoint with known Basic Auth credentials and attempting introspection queries. The scanner checks if introspection is enabled and whether the Basic Auth implementation properly restricts access to schema information.
During manual testing, use tools like curl or Postman to send introspection queries with valid Basic Auth headers. If you receive detailed schema information, your implementation is vulnerable. Pay special attention to error messages—generic errors that don't reveal schema information are preferable to detailed introspection responses.
Monitor your API logs for unusual introspection query patterns. Legitimate clients rarely need full schema information in production. Set up alerts for any requests containing "__schema" or other introspection fields when they originate from authenticated Basic Auth sessions.
Basic Auth-Specific Remediation
Remediating GraphQL introspection vulnerabilities in Basic Auth contexts requires both configuration changes and code-level fixes. The most effective approach combines disabling introspection in production with proper credential validation.
First, disable introspection in your production GraphQL server:
// Apollo Server - disable introspection in production
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
context: ({ req }) => {
const credentials = basicAuth(req);
if (!credentials) {
throw new AuthenticationError('Basic Auth required');
}
return { user: credentials.name };
}
});
For Express-based implementations, add middleware that validates credentials before GraphQL execution:
const basicAuthMiddleware = (req, res, next) => {
const credentials = basicAuth(req);
if (!credentials || credentials.name !== process.env.API_USER || credentials.pass !== process.env.API_PASS) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="API"');
res.end('Access denied');
return;
}
req.user = credentials.name;
next();
};
app.use('/graphql', basicAuthMiddleware, graphqlMiddleware);
Implement field-level authorization to ensure users can only access data they're permitted to see:
const resolvers = {
Query: {
user: (parent, args, context) => {
if (context.user !== args.id && context.userRole !== 'admin') {
throw new ForbiddenError('Not authorized');
}
return db.getUser(args.id);
}
}
};
Consider implementing rate limiting on Basic Auth endpoints to prevent credential brute-forcing attempts. Use libraries like express-rate-limit to restrict the number of authentication attempts per IP address or user account.
Regularly audit your Basic Auth credentials and rotate them frequently. Store credentials in secure vaults rather than configuration files, and use environment variables with proper access controls. Implement logging and monitoring to detect unusual authentication patterns that might indicate credential compromise.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |