Exploiting GraphQL
Intro
GraphQL is a language for APIs that enables you to query and manipulate data through a flexible syntax. GraphQL based services have blown up over the last few years in popularity. From a hackers perspective, what should we be focusing on?
At Assetnote, we spend a lot of time investigating the inherent security flaws within modern technologies that are widely deployed on external attack surfaces.
There are many different implementations of GraphQL servers, and hence, the techniques listed in this blog post may not apply uniformly, however, we do cover techniques that are likely to affect most GraphQL implementations.
We have implemented these GraphQL security checks within our Attack Surface Management platform, and our team has also developed a tool which is capable of attempting most of the techniques listed in this blog post, against any GraphQL API.
BatchQL
BatchQL is a GraphQL security auditing script with a focus on performing batch GraphQL queries and mutations. This script is not complex, and we welcome improvements.
When exploring the problem space of GraphQL batching attacks, we found that there were a few blog posts on the internet, however no tool to perform GraphQL batching attacks.
GraphQL batching attacks can be quite serious depending on the functionalities implemented. For example, imagine a password reset functionality which expects a 4 digit pin that was sent to your email. With this tool, you could attempt all 10k pin attempts in a single GraphQL query. This may bypass any rate limiting or account lockouts depending on the implementation details of the password reset flow.
Here’s what the output from BatchQL looks like when in detection mode:
Detections
This tool is capable of detecting the following:
- Introspection query support
- Schema suggestions detection
- Potential CSRF detection
- Query name based batching
- Query JSON list based batching
Attacks
Currently, this tool only supports sending JSON list based queries for batching attacks. It supports scenarios where the variables are embedded in the query, or where they are provided in the JSON input.
Using BatchQL
Download the tool from GitHub: https://github.com/assetnote/batchql
Check out the README at the following URL for more instructions on how to use BatchQL: https://github.com/assetnote/batchql/blob/master/README.md
Introspection
One of the powerful features of GraphQL is that comprehensive documentation can be generated for any GraphQL API through an introspection query. When introspection is possible, an attacker can obtain the GraphQL schema and understand the entire attack surface of the API.
Upon coming across a GraphQL API, the first step is usually to run an introspection query to obtain a copy of the schema. The schema will help with understanding the attack surface of the exposed GraphQL API.
We recommend using the following Chrome Extension to load up an interactive documentation view, if the introspection query is working: Altair Chrome Extension.
The raw introspection query can be found below:
Show Introspection Query
Suggestions
So, the introspection query doesn’t work because it has been disabled. What now?
The next step is to check whether or not the GraphQL API is returning schema suggestions. The suggestions feature can be leveraged to recover parts of the GraphQL schema.
Check out the presentation by Nikita Stupin where they discuss the process of recovering the GraphQL schema through the suggestions returned by the GraphQL API: GraphQL APIs from bug hunter’s perspective.
In addition to the presentation above, Nikita also released an excellent tool named Clairvoyance which is capable of recovering a GraphQL schema in an automated fashion based off the schema suggestions and further enumeration.
If you’re having issues recovering the schema using Clairvoyance, then give the fork Clairvoyancex a go. This fork also has support for a HTTP proxy, so that you can debug the recovery process as it runs.
We highly suggest you attempt to recover the schema when introspection is disabled. It will often inform you of the attack surface that may be exploitable to other issues.
CSRF
CSRF attacks are often possible against GraphQL APIs that rely on the cookie for authentication and do not require any special headers or tokens to be sent in the HTTP request.
When assessing a GraphQL API, we recommend checking for whether or not the API requests are vulnerable to CSRF attacks.
In our tool BatchQL, we attempt to fingerprint scenarios where a GraphQL API may be vulnerable to CSRF attacks. We do this by sending a GraphQL query via GET and POST and seeing if the query is being evaluated.
This may not be a fool proof way to determine whether or not a GraphQL API is vulnerable to CSRF attacks, however it is a good indicator to perform further analysis to confirm whether or not CSRF is possible.
You can replicate the behaviour of our tool by sending the following requests and seeing if the GraphQL API is responding:
- GET based CSRF
- POST based CSRF
If the response contains something like this:
It may be vulnerable to CSRF attacks.
Please do not submit this indication as a bug report. Further analysis needs to be done to prove the impact that a CSRF attack could have on the GraphQL API.
Look for mutations that may be sensitive and perform actions that could prove the impact of a CSRF attack before submitting anything to bug bounty programs.
JSON list based batching
When sending a GraphQL query, a single query may look like the following:
As seen in the query above, it consists of a single JSON dictionary containing a single query.
Many GraphQL implementations support sending batch queries by providing a JSON list of queries, like shown below:
In this case, a JSON list of queries is provided to the GraphQL server. If the GraphQL API supports this form of batching queries, it will respond with something like this:
Indicating that server-side batching was performed and both of the queries from the request were executed successfully.
Query name based batching
If the GraphQL API you’re attacking does not support JSON list based batching, then we suggest you try query name based batching attacks.
The following GraphQL query demonstrates how this attack works:
If the response contains something like this:
This means that query name based batching is supported for this GraphQL API.
Our tool <span class="code_single-line">BatchQL</span> doesn’t currently support query name based batching attacks. For a PoC to construct your own query name based batching attacks, check out the following gist.
Conclusion
There are a number of avenues to explore when it comes to GraphQL exploitation vectors. The tool BatchQL can be used to detect some of these GraphQL related issues and also exploit JSON list based query batching vulnerabilities.
More Like This
Ready to get started?
Get on a call with our team and learn how Assetnote can change the way you secure your attack surface. We'll set you up with a trial instance so you can see the impact for yourself.