17 Jan, 2023

GraphQL penetration testing methodology

Penetration Testing as a service (PTaaS)

Tests security measures and simulates attacks to identify weaknesses.

Introduction to GraphQL

GraphQL is open-source query language designed to build APIs in various languages, which become a great alternative to well established API like REST due to its ease of use. The very difference is that in GraphQL you can use single endpoint and send bunch of parameters you need in the one request which is pretty structured and flexible, while in the REST you need to send specific parameters to specific endpoints and all the dependences between them in the server may be very complicated to deal with.

From a client’s point of view, GraphQL is a unified way to access all the application’s data sources that may be written in the different languages. Server-side, GraphQL is an engine that maps the user queries to actual data in the database. It is essentially a query language designed to traverse the application data graph and return the data user is asking for. For additional information about key differences between GraphQL and REST, click here.

Key features

As an API, GraphQL implements all of the CRUD functions in its own way: you read data using queries and manipulate with it through mutations. Also, you can “subscribe” to updates specific information on the server in real-time (due to WebSocket that build in GraphQL) using subscription.

In other words:

Queries – Select Statements. Mutations – Insert/Update Statements. Subscription – Updates when a mutation happens.

GraphQL APIs are organized in terms of types and fields, not endpoints. You can access the full capabilities of all your data from a single endpoint.

GraphQL services implement a schema which is capabilities document that has a list of all the questions which the client can ask the GraphQL and set the limits of what can be answered by the GraphQL layer. Schemas and Types – Define Object Types and Fields (Object and Attributes).

Nodes – Objects with fields. Sometimes it allows us to access objects directly by ID and may cause Authorization bypass. Edges – Connections between objects that include some data. Often developers secure nodes but forget about edges!

Instruments to use

IDE: graphql-ide / altair-graphql-client / graph-playground

Visualize: graphql-voyager

Training: graphql-github-explorer / public-graphql-apispentestlab / hackmegraph / pentestlab

Useful: json-to-graphql-query / GraphQLmap / hackerone

Before the very begin

Look for endpoints below. Some of them may disclose sensitive information or allow to have access to the GraphQl console of the server.

The full list of endpoints:

https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/graphql.txt

./graphql /v1/graphql /v2/graphql
/graphql/console /v1/graphql/console /v2/graphql/console
/graphql.php /v1/graphql.php /v2/graphql.php
/graphiql /v1/graphiql /v2/graphiql
/graphiql.php /v1/graphiql.php /v2/graphiql.php
/explorer /v1/explorer /v2/explorer
/altair /v1/altair /v2/altair
/playground /v1/playground /v2/playground

Also add ?debug=1  to the URL

Introspection queries

As a strongly typed language, GraphQL utilizes a type system: GraphQL services implement a schema which is essentially a comprehensive description of all available data and ways to interact with it: all the types, fields, API calls. That doesn’t sound like the information you would share with anybody, which brings us to the first common vulnerability.

Default configuration in GraphQL is Introspection that may let user to see all possible queries, types and so on it supports in Response body by sending special Query in Request POST body. This may lead to Information Disclosure vulnerability.

Example for Introspection query code here or you can grab code directly from graphql-voyager in order to visualize dependencies between parameters schema there.

But what if Introspection is disabled? First, some requests may not be disabled! Try all possible variants of them.

Try to search for subdomains with /dev.example.com and /staging.example.com endpoints. Introspection can be disabled in production, but not in the developing stage. Also try to put all fields that logically can be in the schema and check for sensitive information in Response body. Remember that if you close enough to the right field, GraphQl will suggest the correct one (it’s a feature of Apollo server).

Note! Always watch for error messages to find sensitive/glue information inside the JSON that comes back due to GraphQL HTTP Response is always 200 OK and doesn’t have typically HTTP errors.

Authorization

Since the GraphQL framework does not provide any means for securing your data (as well as Input Validation, Query Whitelisting, Rate Limiting), developers are in charge of implementing Access Control as stated in the documentation. Authorization is no built-in feature, so it’s up to developers to implements an authorization logic. By the way, Access Control and Data Disclosure are the most common vulnerabilities in GraphQL.

App should be protected with an authentication middleware, but still there can be problems if specific parameters in Query fields in schema set up with protection and some of them didn’t. If so, you may modify a legitimate GraphQL query such that it returns sensitive information.

Sometimes authorization is enabled only for specific queries, but not for other API calls (especially when it’s new-build fields features).

If access control is implemented at the GraphQL layer rather than the business logic layer (according to the GraphQL recommendation) or simply implemented poorly, you might encounter vulnerabilities like IDOR.

Due to this, first you should check is bypassing Token session management (send request without it).

For example, using Burp Suite:

Another way to bypass the authentication is use nested queries as root by simply leave only nested query in the response.

Example below:

SQL and NoSQL Injections   

When the application doesn’t have, for example, parameterized queries implementation it may be vulnerable to the SQL injection attacks. GraphQL doesn’t have any input validation by itself, so it’s up to the developers to implement so. Another problem is when some variables not sanitized properly before rendering and cause to exploit even old SQL injection payloads.

An SQL database does not distinguish between authorized and unauthorized queries — it just executes them. It goes without saying consequences might be devastating: bypassing authentication, sensitive information leakage, and malicious code execution. Examples of SQL injection:

You should consider is that today’s many APIs with GraphQL are connected to MongoDB and use JSON custom scalar types, so you have to look into the NoSQL injection here. When build schema the developer should set the specific type of the query in every field (e.g., Int, Bool, String, Float, JSON etc.) and using simple scalar types not enough to fully concretize the input and output of the application. So that’s where we can try to exploit this issue.

Note! You can use tools like sqlmap to look for injection paths by saving your HTTP request with query fields to the request.txt file and test it there.

DoS attack

Sends a costly query designed to overload the server and increases its spending on requests. A typical example of an attack would be a deep nested query. If not handled properly, such requests take forever to run and consume all the server’s computation powers, thus rendering it unresponsive for other users. Example of cycled nested queries:

But more common and usable request will come in form of a JSON over an HTTP POST request like this and here we are dealing with the amount of JSON bytes that comes to the server.

GraphQL security tools 

Setting up the testing environment.

Damn Vulnerable GraphQL Application on Kali Linux

https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application

This is the testing environment (website which is hosted locally) for practicing pentester’s skills and testing GraphQL security/scans/pentest tools. Have fun!

1. Clone the repository:

git clone https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application

2. Open the folder with app cd Damn-Vulnerable-GraphQL-Application/ and run:

sudo docker build -t dvga .

sudo docker run -t -p 5013:5013 -e WEB_HOST=0.0.0.0 dvga

3. Open the browser and navigate to http://localhost:5013

Done! Make sure that all requirements for app are satisfied. Now we can test all tools using http://localhost:5013

graphw00f

https://github.com/dolevf/graphw00f

It helps you to determine endpoints on the website specific with GraphQL implementation. For example, we have example.com and search for example.com/graphql

It helps you to fingerprint the website, which is means – identifying the type and version of web server that a website is running on. Knowing this information, we can check which configurations and known vulnerabilities exist for the server and try to exploit them.

1. Clone the repository:

git clone https://github.com/dolevf/graphw00f.git

2. Open the folder with app cd graphw00f/ and run for detection endpoints:

python3 main.py -d -t  http://localhost:5013/

3. Now we can check endpoint http://localhost:5013/graphql for fingerprinting:

python3 main.py -f -t  http://localhost:5013/graphql

GraphQL Cop

https://github.com/dolevf/graphql-cop

It’s python utility that helps you to test common vulnerabilities in GraphQL. After results you should manually check the potential vulnerabilities, but still this tool gives you a clue for threads you should check first. Even if you don’t know the endpoint with graphql on the website, this tool will find it by itself with -f command.

1. Clone the repository:

git clone https://github.com/dolevf/graphql-cop

2. Open the folder with app cd graphql-cop/ and run scanner:

python graphql-cop.py -t http://localhost:5013

Nozaki

https://github.com/htrgouvea/nozaki

It helps you to make a fuzzing and bruteforcing with its libraries (numbers, words etc.) for testing Denial of Service vulnerability and searching endpoints, accepted headers, HTTP methods and paths.

1. Download and open folder with tool:

git clone https://github.com/NozakiLabs/nozaki && cd nozaki

2. Install:

cpan install Find::Lib JSON YAML::Tiny Mojo::UserAgent

3. Example of scanning (return only 200 OK Response results):

perl nozaki.pl --url http://localhost:5013/ --return 200

4. Set a specific wordlist and HTTP method:

perl nozaki.pl -m GET -u http://localhost:5013/ --return 200 --wordlist example.txt

BatchQL

https://github.com/assetnote/batchql

It helps you to detect possible batching attack (possibility to send duplicate queries with parameters in the one query per request that cause server overloading and may increase spendings on request by server). Also, it detects if Introspection is enabled and if cross-site request forgery is possible.

1. Clone the repository:

git clone https://github.com/assetnote/batchql

2. Open the folder with app cd batchql/ and run scanner:

python batch.py -e http://localhost:5013/graphql

GraphQLmap

https://github.com/swisskyrepo/GraphQLmap

It helps you to use Introspection, test SQL and NoSQL injections. To test SQL/NoSQL injections you should provide any Queries from the target URL.

1. Clone the repository:

git clone https://github.com/swisskyrepo/GraphQLmap

2. Open the folder with app cd GraphQLmap/ and install:

sudo python setup.py install

3. Run the scanner. Notice that URL must have /qraphql endpoint:

graphqlmap -u http://localhost:5013/graphql

4. print dump_via_introspection command.

Clairvoyance

https://github.com/nikitastupin/clairvoyance

Useful tool for brute forcing Schema when Introspection is disabled. If you faced issues during run the tool, try install and run as root user through root terminal. Also you may face issues trying to scan localhost.

1. Install via pip:

pip install clairvoyance

2. Run the program using wordlist txt document and get JSON file with results:

python3 -m clairvoyance -o result.json http://localhost:5013/graphql

See results in JSON file.

ShapeShifter

https://github.com/szski/shapeshifter

Scan GraphQL endpoints and extract Introspection Schema.

1. Clone the repository and build via docker (see in the link):

git clone https://github.com/assetnote/batchql

2. Run the program using wordlist txt document and get JSON file with results:

docker run -it shapeshifter scan --url http://example.com

Addition information for study

First of all, documentation!

https://graphql.org/learn/

Research on GraphQL – Study what is GraphQL

https://github.com/righettod/poc-graphql

graphql-goat – Vulnerable GraphQL application to learn about GraphQL security

https://github.com/amanvir/graphql-goat

developer-security-training – All Labs of the Security for Developers Training

https://github.com/NovatecConsulting/developer-security-training

All the publicity known GraphQL APIs for training and exploring

https://github.com/IvanGoncharov/graphql-apis

A repository to show off to the community methods of testing NestJS including Unit Tests, Integration Tests, E2E Tests, pipes, filters, interceptors, GraphQL, Mongo, TypeORM, and more!

https://github.com/jmcdo29/testing-nestjs

Graphql-Pentest – Some notes for graphql pentest during CTF

https://github.com/robyfirnandoyusuf/Graphql-Pentest

Conclusion

GraphQL systems, like any other API, are susceptible to a broad range of vulnerabilities. Understanding potential dangers is crucial in order to take the steps necessary to efficient pentest an application.

Cybersecurity doesn’t have to be complicated. With CQR company, you get a team of professionals to perform a complete security check of your app, whether it runs on REST, GraphQL, or any other API. Schedule a free demo today or learn more about our workflow.

While we covered some of the most common vulnerabilities, there are many other dangers out there. With time some vulnerabilities are addressed by developers while new vulnerabilities are being found and exploited, attacks get more sophisticated, and hackers more creative.

Other Services

Ready to secure?

Let's get in touch