Graphql Introspection with Mutual Tls
How Graphql Introspection Manifests in Mutual Tls
GraphQL introspection is a powerful feature that allows clients to query an API's schema to discover available types, fields, and operations. When GraphQL APIs are deployed behind Mutual TLS (mTLS) authentication, the introspection endpoint can still be exposed to any client that possesses a valid client certificate, creating a significant security risk.
In mTLS environments, the GraphQL introspection query typically manifests through the following attack pattern:
POST /graphql HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ
{
"query": "query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ... } } }"
}
The critical vulnerability occurs because mTLS verifies client identity but doesn't restrict what authenticated clients can do. An attacker with a stolen or compromised client certificate can access the introspection endpoint and retrieve the entire GraphQL schema, including:
- All available queries, mutations, and subscriptions
- Field arguments and their types
- Enum values and custom scalar types
- Interface and union definitions
- Database table structures and relationships
- Business logic implementation details
This information disclosure becomes particularly dangerous in mTLS contexts because the certificate authentication creates a false sense of security. Organizations often assume that because clients are authenticated via certificates, they should have broad access to schema information. However, this assumption violates the principle of least privilege.
Real-world exploitation often follows this pattern:
- Attacker obtains a client certificate through various means (phishing, insider threat, certificate misconfiguration)
- Certificate allows mTLS handshake and GraphQL endpoint access
- Introspection query reveals schema structure
- Attacker crafts targeted queries to extract sensitive data
- Business logic vulnerabilities are discovered through schema analysis
The mTLS layer doesn't prevent introspection abuse because the certificate authentication is separate from GraphQL authorization. Even with perfect certificate management, the introspection endpoint remains a critical attack surface that must be explicitly secured.
Mutual Tls-Specific Detection
Detecting GraphQL introspection vulnerabilities in mTLS environments requires a multi-layered approach that examines both the TLS layer and GraphQL layer independently.
Network-level detection involves monitoring mTLS handshakes and certificate usage patterns. Look for:
- Multiple client certificates accessing the same GraphQL endpoint
- Unusual certificate rotation patterns
- Certificates with overly broad permissions accessing sensitive APIs
- Failed mTLS handshakes followed by successful ones (potential certificate testing)
For GraphQL-specific detection, middleBrick's mTLS-aware scanning identifies introspection exposure through several methods:
# middleBrick scan command for mTLS endpoints
middlebrick scan https://api.example.com/graphql \
--mtls-cert client-cert.pem \
--mtls-key client-key.pem \
--mtls-ca ca-cert.pem
The scanner tests for introspection accessibility by attempting standard introspection queries and analyzing the response structure. Key detection patterns include:
| Detection Method | What It Identifies | False Positive Risk |
|---|---|---|
| Introspection Query Response | Complete schema structure | Low |
| Schema Field Analysis | Sensitive field exposure | Medium |
| Authentication Bypass Testing | Certificate privilege escalation | Low |
| Rate Limiting Assessment | Introspection abuse potential | Medium |
Additional detection techniques include:
- Monitoring GraphQL query patterns for schema discovery attempts
- Analyzing certificate usage logs for unusual access patterns
- Implementing mTLS client certificate revocation monitoring
- Using web application firewalls to detect introspection query signatures
middleBrick specifically flags mTLS introspection issues with severity ratings based on the sensitivity of exposed schema elements and the potential for privilege escalation through schema analysis.
Mutual Tls-Specific Remediation
Remediating GraphQL introspection vulnerabilities in mTLS environments requires implementing controls at both the TLS and GraphQL layers. The most effective approach combines certificate management with GraphQL-specific authorization.
Certificate-based remediation starts with implementing certificate-based access controls:
# NGINX mTLS configuration with GraphQL restrictions
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /path/to/server-cert.pem;
ssl_certificate_key /path/to/server-key.pem;
ssl_verify_client on;
# Certificate-based access control
if ($ssl_client_s_dn != "CN=graphql-client,OU=API,DC=example,DC=com") {
return 403;
}
location /graphql {
# GraphQL introspection disabled
add_header X-GraphQL-Introspection "disabled" always;
}
GraphQL-level remediation involves implementing schema protection and authorization:
# GraphQL schema with introspection disabled
const { ApolloServer, gql } = require('apollo-server');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'Hello world!'
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV === 'development',
playground: process.env.NODE_ENV === 'development'
});
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
For production environments, implement role-based access control at the GraphQL level:
# JWT-based authorization with mTLS certificate validation
const jwt = require('jsonwebtoken');
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
// Validate mTLS certificate
const clientCert = req.socket.getPeerCertificate();
if (!clientCert.isValid || !clientCert.subject) {
throw new Error('Invalid mTLS certificate');
}
// Validate JWT token
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) throw new Error('Missing authorization token');
const user = jwt.verify(token, process.env.JWT_SECRET);
// Check if user has GraphQL access permissions
if (!user.permissions.includes('graphql_access')) {
throw new Error('Insufficient permissions for GraphQL access');
}
return { user, clientCert };
},
introspection: false,
playground: false
});
Additional remediation strategies include:
- Implementing certificate lifecycle management with automatic revocation
- Using short-lived client certificates with renewal requirements
- Deploying API gateways that enforce GraphQL authorization policies
- Implementing comprehensive logging and monitoring for GraphQL access patterns
- Using middleBrick's continuous monitoring to detect configuration drift
The key principle is defense in depth: mTLS provides authentication, but GraphQL authorization must independently control what authenticated clients can do, including whether they can access schema introspection information.
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 |