HIGH graphql introspectionhmac signatures

Graphql Introspection with Hmac Signatures

How Graphql Introspection Manifests in Hmac Signatures

Graphql Introspection vulnerabilities in HMAC-based API authentication systems occur when attackers can query the GraphQL schema to understand the API structure, then craft malicious requests that bypass or manipulate HMAC signatures. This manifests through several specific attack patterns:

// Vulnerable endpoint exposing introspection
query IntrospectionQuery {
  __schema {
    types {
      name
      fields {
        name
        type {
          name
          kind
        }
      }
    }
  }
}

When HMAC signatures are used for API authentication, attackers can exploit introspection to discover which fields and mutations exist, then craft requests that target specific HMAC-protected endpoints. The vulnerability appears when:

  • Introspection is enabled without authentication requirements
  • HMAC signatures don't validate the full request payload
  • Field-level access controls are missing in the GraphQL schema
  • Attackers can modify request bodies after signature generation

A common manifestation involves discovering mutation endpoints that modify data, then crafting requests that include additional fields not present in the original signed request:

// Original signed request (valid)
mutation {
  createUser(input: {name: "John"}) {
    id
    name
  }
}

// Malicious request after introspection
mutation {
  createUser(input: {name: "John", admin: true}) {
    id
    name
    admin
  }
  deleteUsers {
    success
  }
}

The HMAC signature validation fails to detect these additional fields because the signature was generated for a different payload structure, allowing privilege escalation attacks.

HMAC Signatures-Specific Detection

Detecting GraphQL introspection vulnerabilities in HMAC-based systems requires examining both the authentication mechanism and the GraphQL endpoint configuration. Here's how to identify these issues:

1. Schema Exposure Testing

// Test if introspection is enabled
curl -X POST https://api.example.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "__schema { types { name } }"}'

// Check if schema is accessible without authentication
curl -X POST https://api.example.com/graphql \
  -H "Authorization: HMAC your-signature-here" \
  -d '{"query": "__type(name: \"Mutation\") { name fields { name } }"}'

2. HMAC Signature Validation Analysis

// Check if HMAC validates full payload
const payload = {
  query: 'mutation { createUser(input: {name: "John"}) { id } }',
  variables: {}
};

const signature = generateHMAC(payload);

// Test with modified payload
const maliciousPayload = {
  query: 'mutation { createUser(input: {name: "John", admin: true}) { id } }',
  variables: {}
};

// If signature still validates, there's a vulnerability
const isValid = verifyHMAC(maliciousPayload, signature); // Should be false

3. Field-Level Access Control Verification

// Check if mutations have proper authorization
const introspectionQuery = `
{
  __schema {
    mutationType {
      fields {
        name
        args {
          name
          type { name }
        }
      }
    }
  }
}
`;

// Test if admin-only mutations are accessible
const mutationQuery = `
mutation {
  deleteUser(id: "123") {
    success
  }
}
`;

middleBrick Detection Capabilities

middleBrick automatically scans for these vulnerabilities by:

  • Testing introspection endpoints without authentication
  • Analyzing HMAC signature validation strength
  • Checking for exposed schema information
  • Verifying field-level authorization controls
  • Testing for payload manipulation after signature generation

The scanner identifies specific risk patterns like "Introspection Enabled Without Authentication" and "HMAC Signature Bypass Through Schema Manipulation" with severity ratings based on exploitability.

HMAC Signatures-Specific Remediation

Fixing GraphQL introspection vulnerabilities in HMAC-based systems requires a multi-layered approach. Here are specific remediation strategies:

1. Disable Introspection in Production

// GraphQL.js configuration
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 !== 'production',
  playground: process.env.NODE_ENV !== 'production'
});

2. Implement HMAC Signature Best Practices

// Node.js HMAC implementation with full payload validation
const crypto = require('crypto');

function generateHMAC(payload, secret) {
  const jsonString = JSON.stringify(payload);
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(jsonString);
  return hmac.digest('hex');
}

function verifyHMAC(payload, signature, secret) {
  const expectedSignature = generateHMAC(payload, secret);
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(signature)
  );
}

// Include full request context in signature
function generateSecureHMAC(request) {
  const { method, path, body, timestamp } = request;
  const payloadString = JSON.stringify({
    method,
    path,
    body,
    timestamp
  });
  return crypto.createHmac('sha256', process.env.HMAC_SECRET)
    .update(payloadString)
    .digest('hex');
}

3. Add Field-Level Authorization

// GraphQL.js schema with authorization directives
const { ApolloServer, gql, makeExecutableSchema } = require('apollo-server');

const typeDefs = gql`
  directive @auth(role: String) on FIELD_DEFINITION

  type Query {
    publicData: String
  }

  type Mutation {
    createUser(input: UserInput!): User
      @auth(role: "admin")
    
    deleteUser(id: ID!): Boolean
      @auth(role: "admin")
  }

  input UserInput {
    name: String!
    email: String!
  }

  type User {
    id: ID!
    name: String!
    email: String!
    admin: Boolean! @auth(role: "admin")
  }
`;

const resolvers = {
  Mutation: {
    createUser: (parent, args, context) => {
      if (!context.user || context.user.role !== 'admin') {
        throw new Error('Unauthorized');
      }
      // create user logic
    },
    deleteUser: (parent, args, context) => {
      if (!context.user || context.user.role !== 'admin') {
        throw new Error('Unauthorized');
      }
      // delete user logic
    }
  }
};

4. Implement Rate Limiting and Request Validation

// Express middleware for HMAC validation
const express = require('express');
const rateLimit = require('express-rate-limit');

const app = express();

// Rate limiting to prevent abuse
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP'
});

app.use(limiter);

// HMAC validation middleware
function hmacValidator(req, res, next) {
  const hmacHeader = req.headers['x-hmac-signature'];
  const timestamp = req.headers['x-timestamp'];
  
  if (!hmacHeader || !timestamp) {
    return res.status(401).json({ error: 'Missing HMAC signature' });
  }
  
  // Validate timestamp freshness
  const requestTime = new Date(timestamp);
  const currentTime = new Date();
  const timeDiff = (currentTime - requestTime) / 1000; // seconds
  
  if (Math.abs(timeDiff) > 300) { // 5 minute window
    return res.status(401).json({ error: 'Request timestamp expired' });
  }
  
  // Verify HMAC
  const payload = {
    method: req.method,
    path: req.path,
    body: req.body,
    timestamp
  };
  
  const expectedSignature = generateHMAC(payload, process.env.HMAC_SECRET);
  
  if (!crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(hmacHeader)
  )) {
    return res.status(401).json({ error: 'Invalid HMAC signature' });
  }
  
  next();
}

app.use(express.json());
app.use(hmacValidator);

5. Use middleBrick for Continuous Monitoring

After implementing these fixes, use middleBrick's continuous monitoring to ensure your HMAC-protected GraphQL endpoints remain secure. The Pro plan's CI/CD integration can automatically scan your APIs before deployment, preventing introspection vulnerabilities from reaching production.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

How can I test if my GraphQL endpoint has introspection enabled?

Send a POST request with a simple introspection query like {"query": "__schema { types { name } }"} to your GraphQL endpoint. If you receive a valid schema response without authentication, introspection is enabled. middleBrick can automate this testing across all your endpoints and provide detailed findings about schema exposure risks.

What's the difference between HMAC signature validation and GraphQL field-level authorization?

HMAC signature validation ensures the request hasn't been tampered with and authenticates the client, while field-level authorization controls what data each authenticated user can access within the GraphQL schema. Both are necessary: HMAC prevents request manipulation, and field-level auth prevents privilege escalation even if an attacker discovers schema information through introspection.