Skip to main content
Create your own
Lesson illustration

Testing GraphQL for Common Vulnerabilities

Hello! Welcome to your lesson on advanced web and API security.

In our last session, we explored how implementation flaws in the OAuth 2.0 protocol can be exploited to achieve account takeover. We focused on the state parameter for CSRF protection and the critical importance of a securely configured redirect_uri.

Today, we continue our journey into API security by examining GraphQL, a powerful and flexible query language for APIs that has become increasingly popular in modern web and mobile applications. While GraphQL offers developers significant advantages over traditional REST APIs, its complexity introduces unique and often severe security vulnerabilities.

This lesson will equip you to meet the learning outcome: Test GraphQL endpoints for common vulnerabilities like information disclosure via introspection and batching attacks. We will move from discovering an API's entire structure to leveraging its own features against it for high-impact results.

1. What is GraphQL and Why Does it Matter for Security?

Before we attack it, let's understand what makes GraphQL different. Unlike REST, where you have multiple endpoints each returning a fixed data structure (e.g., /users/1, /posts/12), a GraphQL API typically exposes a single endpoint. The client specifies exactly what data it needs in a single request, preventing the common problems of over-fetching (getting too much data) or under-fetching (needing to make multiple requests).

Your background in computer science will make the concept of a query language for an API intuitive. The key security implication is that this flexibility shifts significant power to the client. An attacker who can submit arbitrary GraphQL queries can potentially ask for more data than a developer ever intended to expose.

GraphQL for Bug Bounty Hunters

For a concise overview of GraphQL from a security perspective, watch this introductory segment from the talk 'GraphQL for Bug Bounty Hunters' by AmrSec.

Watch from the beginning to 03:43. The speaker explains what GraphQL is, how it differs from REST, and why its flexibility introduces an interesting attack surface for security testers.

2. Information Disclosure via Introspection

The most critical first step in testing a GraphQL endpoint is to understand its schema. The schema is the blueprint of the entire API—it defines every possible query, every data type, and every action (called a "mutation") that the API supports.

Many GraphQL servers have a built-in feature called introspection, which allows you to query the schema itself. When enabled in a production environment, it's like handing an attacker the architectural plans to your entire application.

The standard introspection query is quite long, but it's a well-known payload that you can use to ask the server to describe itself.

GraphQL Introspection Query and Schema Response
This image shows a standard introspection query being sent in an HTTP request (left) and the server responding with the full API schema in JSON format (right). This is a classic information disclosure vulnerability.

Reporting that "introspection is enabled" is a low-impact finding. The real skill, and what separates beginners from experts, is analyzing the disclosed schema to find high-impact vulnerabilities.

How Hackers Analyze GraphQL Responses for High-Impact Bugs?

The video 'How Hackers Analyze GraphQL Responses for High-Impact Bugs?' by Medusa provides an outstanding, step-by-step guide on how to turn an introspection finding into a critical vulnerability. This is a masterclass in practical GraphQL hacking.

This video is the core of our lesson. Watch from 01:32 to 24:02. The content is broken down as follows: (01:32 - 08:07): Understand basic GraphQL queries and use a simple introspection query to list all available operations. (08:07 - 10:24): Learn to query for the 'types' of fields (e.g., string, object) to understand the data structure. (10:24 - 15:50): The presenter explains the components of the full introspection query. (15:50 - 24:02): This is the most important part. Watch how the presenter analyzes the full schema, discovers a sensitive adminDump query linked to a userInternal object, and crafts a new query to leak password hashes and API keys.

As you saw in the video, the process is:

  1. Run the introspection query to get the full schema.
  2. Search the schema for interesting keywords like "admin", "internal", "password", "key", etc.
  3. Identify a query or mutation that looks sensitive (e.g., adminDump).
  4. Find the object type that this query returns (e.g., userInternal).
  5. Examine the fields of that object type for sensitive data (e.g., passwordHash, apiKey).
  6. Craft a new query to execute the sensitive operation and request the sensitive fields.
Test your understanding!

You are analyzing an introspection response and find the following snippets:

Snippet 1: A query definition.

{
  "name": "getInvoice",
  "args": [
    {
      "name": "invoiceId",
      "type": { "name": "ID" }
    }
  ],
  "type": {
    "name": "Invoice",
    "kind": "OBJECT"
  }
}

Snippet 2: An object definition.

{
  "name": "Invoice",
  "kind": "OBJECT",
  "fields": [
    { "name": "id" },
    { "name": "amount" },
    { "name": "status" },
    { "name": "customerDetails" }
  ]
}

Based on this, you suspect an Insecure Direct Object Reference (IDOR) vulnerability. What GraphQL query would you write to test this hypothesis by trying to access invoice 42?

Show answer

You would craft a query that calls getInvoice with the invoiceId argument, and in that query, you would request the fields from the Invoice object you want to see. A good test would be:

query {
  getInvoice(invoiceId: "42") {
    id
    amount
    status
    customerDetails
  }
}

If the API returns the details for invoice 42 without checking if your current user is authorized to view it, you have confirmed an IDOR vulnerability.

What if Introspection is Disabled?

In a hardened environment, introspection will be disabled. However, GraphQL's helpful nature can still be abused. The field suggestion feature, which suggests correct field names when you make a typo, can be used to enumerate the schema piece by piece.

For example, sending a query for a non-existent field like { users { nam } } might return an error like: Cannot query field "nam" on type "User". Did you mean "name"?

This error-based leakage allows an attacker to guess and confirm valid field names, slowly reconstructing the schema.

Hacking GraphQL endpoints in Bug Bounty Programs

The article 'Hacking GraphQL endpoints in Bug Bounty Programs' from YesWeHack discusses this technique as a fallback when introspection is off.

Read the section 'GraphQL introspection disabled? Try a fuzzing attack instead'. It explains how the field suggestion feature can be abused to reveal schema information.

3. Denial of Service via Batching Attacks

GraphQL allows clients to "batch" multiple operations into a single HTTP request. This is done by sending a JSON array of query objects instead of a single object.

GraphQL Batching Attack Example
This image shows a JSON array containing multiple queries. This allows an attacker to execute many operations within a single HTTP request, which is the basis of a batching attack.

This feature can be abused in two primary ways:

  1. Bypassing Rate Limiting: If rate limiting is implemented at the HTTP request level (e.g., "100 requests per minute"), an attacker can use batching to send thousands of logical operations (like login attempts or OTP guesses) in a single request, completely bypassing the security control.

  2. Denial of Service (DoS): If a specific query is known to be resource-intensive (e.g., a complex data search or a system maintenance task), an attacker can send a batch of hundreds of these queries at once. The server will try to process all of them, potentially exhausting its CPU or memory and becoming unavailable to legitimate users.

Damn Vulnerable GraphQL Application - Solutions

Let's read about how batching is used for DoS attacks from the 'Damn Vulnerable GraphQL Application' project documentation. It provides a clear explanation and a practical Python script.

Read the section 'Denial of Service :: Batch Query Attack'. Pay close attention to the problem description and the simple Python code snippet that demonstrates how to construct a batched request.

The key takeaway is that if you find any way to bypass authentication or cause high resource usage with a single GraphQL query, you can almost always amplify its impact dramatically using a batching attack.

Conclusion

GraphQL is a double-edged sword: its flexibility is a boon for developers but a goldmine for attackers if not secured properly. As a penetration tester or bug bounty hunter, understanding its unique attack surface is non-negotiable.

Key Takeaways:

  • Introspection is a Treasure Map: An enabled introspection endpoint is your highest priority discovery. It provides a complete roadmap of the API's functionality.
  • Analyze the Schema for Sensitive Operations: Don't just report that introspection is on. Analyze the schema to find hidden or admin-only queries/mutations and craft exploits to access sensitive data or functionality.
  • Abuse Error Messages: If introspection is disabled, use field suggestions and other verbose errors to manually reconstruct parts of the schema.
  • Batching Amplifies Impact: Batching attacks are a powerful technique to bypass request-based rate limiting or to cause a Denial of Service by chaining resource-intensive queries.

Next Lesson Preview:

In our final lesson for this module, we will explore one of the most creative and impactful aspects of hacking: vulnerability chaining. You will learn how to combine multiple, seemingly lower-risk vulnerabilities (like some we've already discussed) to create a critical path to compromise. This will directly address the learning outcome: Chain multiple web vulnerabilities (e.g., SSRF + Command Injection) to achieve a critical impact.

Can't find a good explanation? Sign up and we'll make it for you

Sign up