Page cover
githubEdit

chart-bulletGraphQL Injections

Data query and manipulation language for APIs

chevron-rightCore Conceptshashtag
circle-info
  • Uses HTTP/HTTPS, typically over POST requests.

  • JSON-based queries and responses.

  • Typically uses a single endpoint for all operations.

  • Apollo Server commonly uses port 4000 as its default when started without configuration.

  • Express-based GraphQL servers frequently use port 3000, simply because that's the default for many Express setups.

  • Introspection allows clients to query the API schema for available operations and data types.

circle-info

Schema

Every GraphQL API has a schema that defines:

  • Types - What objects exist

  • Queries - How to READ data

  • Mutations - How to WRITE/CHANGE data

circle-info

Types

A Type defines the structure of an object:

type User {
  id: ID!
  email: String!
  role: String!
  inviteCode: String
  verified: Boolean!
}

This means:

  • User is an object

  • It has 5 fields: id, email, role, inviteCode, verified

  • ! means required/non-null

  • No ! means optional (can be null)

circle-info

Queries

Queries are like GET requests in REST:

Schema Example
type Query {
  me: User
  systemStatus: String
  incidentReports: [IncidentReport]
}
Request Example
query {
  me {
    id
    email
  }
}

When a query returns an OBJECT type (like User), you must specify which fields you want. You can't just say me , you must say me { id email }

circle-info

Mutations

Mutations are like POST/PUT/DELETE in REST:

Schema Example
type Mutation {
  login(email: String!, password: String!): User
  register(email: String!, password: String!): User
  regenerateInviteCode: User
}
Request Example
mutation {
  login(email: "test@test.com", password: "pass123") {
    id
    email
    verified
  }
}
  • login takes 2 arguments: email and password

  • It returns a User object

  • We specify which User fields we want back: id, email, verified

circle-info

Introspection

introspection allow to query the schema itself.

If introspection is enabled in production, attackers can discover the entire API structure.

circle-info

The GraphQL Request Format

Every GraphQL request has this structure:

{
  "query": "your GraphQL query here",
  "variables": { "optional": "values" }
}
chevron-rightTesting Checklisthashtag
circle-info

Key GraphQL Security Issues

  • Introspection in Production

  • Over-fetching Sensitive Data

  • Mutation Side Effects

  • Test Query Depth and Complexity: Check server limits on nested or complex queries to prevent performance issues.

  • Validate Input Types and Arguments: Test inputs with invalid data to identify validation weaknesses.

  • Examine Query Aliasing and Batching: Test for data leaks via aliased queries and batched requests.

  • Check for Introspection Misuse: Ensure introspection doesn't expose sensitive or unnecessary schema details.

  • Assess Authorization Controls: Confirm proper enforcement of access controls for queries and operations.

  • Evaluate Rate Limiting: Ensure the API handles excessive or malicious requests effectively.

  • Fuzz Mutations: Test for security and validation flaws in mutation operations.

chevron-rightIntrospection Querieshashtag
circle-info

For Burp Suite, wrap the queries in JSON.

circle-info

Discovery

circle-info

Intelligence Gathering

circle-info

Attack Preparation

Understand exactly what data you need to send to execute an attack

  • You cannot hack a mutation without knowing what arguments it accepts.

  • Once you find a query that returns a User, run this to see if it contains sensitive fields that you can request.

circle-info

Response Analysis

Determine if you can dump data in bulk (Lists) or if you get detailed objects

  • If a mutation returns a User object, you might be able to ask for private user data immediately after creating/updating them.

  • If you find a query that returns a type of kind: LIST (e.g., [User]), you can potentially ask for every user in the database in a single request, rather than just one.

chevron-rightExecuting Mutationshashtag

Once you have found a Mutation name and its required Arguments, use these templates to attack it.

circle-info

Mutation with NO Arguments

Use this when the mutation acts on the current logged-in user (like regenerateInviteCode or logout).

circle-info

Mutation with INLINE Arguments

Use this for simple mutations (like login or deleteUser) where you have hard-coded values.

  • Remember to escape quotes (\") if you are inside a JSON string.

circle-info

Mutation with VARIABLES

It separates the logic from the data, making it much easier to fuzz specific parameters.

  • The query part: Defines what you are doing and types of data (String!).

  • The variables part: Contains the actual payload.

Last updated