Graphql Introspection in Aspnet with Hmac Signatures
Graphql Introspection in Aspnet with Hmac Signatures — how this specific combination creates or exposes the vulnerability
GraphQL introspection in an ASP.NET endpoint becomes a security concern when an API relies on HMAC signatures only for request authentication but does not restrict introspection operations. Introspection queries (e.g., an HTTP POST with Content-Type application/json and a query like { __schema { queryType { name } } }) return the full schema, including types, queries, and mutations. If the endpoint validates an HMAC signature to confirm the request originates from a trusted source but does not apply authorization checks on introspection, an authenticated caller can harvest detailed structural information. This can reveal sensitive field names, query patterns, and resolver behavior, which attackers may use to refine injection, IDOR, or BOLA attacks.
In ASP.NET, this often occurs when GraphQL middleware is configured to accept requests authenticated via HMAC without additional operation-level policies. The HMAC is typically computed over selected parts of the request (method, path, timestamp, and body), ensuring integrity and origin, yet it does not enforce whether the operation is allowed. Because introspection is a built-in GraphQL capability, it remains reachable if the route is accessible. Attackers can send crafted introspection queries to learn argument names, input structures, and object relationships, which can be combined with other weaknesses such as BOLA or IDOR discovered through introspection to escalate impact.
When combined, the presence of HMAC signatures and exposed introspection creates a scenario where authentication does not imply authorization for schema discovery. For example, an API might validate HMAC to allow trusted internal services to call mutation operations, but if introspection is not explicitly disabled or gated, any client with valid HMAC credentials can still retrieve the schema. This increases risk because detailed schema knowledge enables more precise attacks, such as parameter tampering or targeting specific nested objects. To mitigate this, schema access should be treated as a first-class security boundary, independent of transport-level integrity checks like HMAC.
Hmac Signatures-Specific Remediation in Aspnet — concrete code fixes
To secure GraphQL introspection in ASP.NET while retaining HMAC-based request authentication, explicitly control schema exposure and enforce authorization on operations. Below are concrete code examples demonstrating how to disable introspection and gate operations using HMAC validation and policy-based authorization.
1. Disable GraphQL introspection in ASP.NET
Configure the GraphQL server to disable introspection in production environments. Using GraphQL.Server.Transports.AspNetCore and GraphQL.Server.Core, you can set introspection disabled via schema configuration:
var schema = SchemaBuilder.New()
.AddTypes(typeof(QueryType).Assembly, typeof(QueryType).Namespace)
.AddSystemTextJson()
.DisableIntrospection()
.Create();
This ensures that introspection queries are rejected regardless of HMAC validity, reducing information leakage while preserving functionality for trusted operations.
2. HMAC validation middleware with operation authorization
Implement HMAC validation in middleware, then enforce per-operation policies. The example below shows HMAC computation and verification in ASP.NET Core, followed by a GraphQL middleware that checks authorization before executing the operation:
// HMAC validation middleware
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/graphql") && context.Request.Method == "POST")
{
using var reader = new StreamReader(context.Request.Body);
var body = await reader.ReadToEndAsync();
context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body));
var timestamp = context.Request.Headers["X-Timestamp"];
var receivedMac = context.Request.Headers["X-Hmac-Signature"];
var secret = Environment.GetEnvironmentVariable("HMAC_SECRET");
var dataToSign = $"{context.Request.Method}{context.Request.Path}{timestamp}{body}";
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var computedMac = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(dataToSign)));
if (!CryptographicOperations.FixedTimeEquals(Convert.FromBase64String(receivedMac), Convert.ToBase64String(computedMac)))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid signature");
return;
}
}
await next();
});
After HMAC validation, apply GraphQL-specific authorization. Use the GraphQL Context to pass user claims and enforce policies per operation type:
app.UseGraphQL("/graphql")
.AddGraphQLServer()
.AddAuthorization(options =>
{
options.AddPolicy("MutationPolicy", policy => policy.RequireClaim("scope", "mutations"));
options.AddPolicy("QueryPolicy", policy => policy.RequireClaim("scope", "queries"));
})
.AddDocumentFromTypes(typeof(QueryType).Assembly)
.AddType()
.AddAuthorization();
This ensures that even when HMAC validates the request origin, individual operations are further restricted based on claims, preventing unauthorized introspection and mutation usage.
3. Schema filtering for introspection
Provide a filtered schema for specific roles, disabling introspection for untrusted consumers:
var filteredSchema = SchemaBuilder.New()
.AddTypes(typeof(QueryType).Assembly, typeof(QueryType).Namespace)
.AddSystemTextJson()
.Create();
app.UseGraphQL("/graphql")
.AddGraphQLServer()
.AddSchema(filteredSchema)
.ModifyOptions(o => o.EnableMetrics = false)
.AddAuthorization();
By combining HMAC integrity checks with explicit schema and operation policies, you reduce the attack surface while maintaining legitimate access patterns.
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 |