GraphQL is one of the commonly used open-source manipulation and data query language for APIs, and runtime for implementing queries for preexisting data. It also serves as an efficient alternative to traditional REST API queries. This open-source language is not associated with a specific backend, which means that it interacts with existing code and data. The client interacts with the GraphQL service, which then interacts with the database via query resolvers during execution.
It enforces a strict typing system, and data is described in a well-defined GraphQL schema. It enables clients to craft a GraphQL query and get what they need. Their schemas can be massive, and from a hacker’s perspective, this presents new challenges. The foundational knowledge of the GraphQL schema and proper tools for automation is necessary to plan an attack.
ImageSource: https://devopedia.org/graphql
The above image contains a query operation on the object ‘paste’. The object takes an argument ‘pId’, which is a string, and a variable ‘$pId’. It is also defined to make this argument dynamic.
Some common examples for GraphQL endpoints are listed below.
Browse SecLists some popular graphql wordlist.
Check for parameters that resemble GraphQL query structure, then locate hidden endpoints by looking out for keywords in the HTML source of your web application or files such as, “query “, “mutation “, “graphql”.
However, the endpoints do not have to follow any specific naming convention. Applications in the wild are known to host their GraphQL service on a separate domain e.g.,graphql.example.com.
After identifying a GraphQL endpoint, the first step would be an introspection query. Most GraphQL instances have introspection enabled by default.
An introspection query is used to probe a GraphQL service for information about the types, queries, mutations & fragments of the available GraphQL schema. This feature allows anyone to see the layout of the entire schema. If the introspection is documented by the developers, then it can be accessed by the GraphQL endpoint via its interactive console (usually /graphiql).
A comprehensive request to perform GraphQL introspection(if enabled) is shown in the following image:
Visit Payloads All The Things to learn more information on the URL encoded & URL decoded variants of the GraphQL introspection query. Tools like GraphQL Raider and InQLare used to gather information about queries and mutations.
We will be looking at a couple of attacks that consist of scenarios specific to the GraphQL implementation like Batched Queries and DoS from Nested Queries. However, classic attacks like SQL injections, Rate Limiting, and Improper Authorization also affect GraphQL implementations.
Batched Queries Attack
GraphQL supports query batching. It enables the client to batch multiple queries or collect the request for multiple object instances through a single GraphQL API call.
This feature of grouping can be abused to create a form of brute force attack. As the client can query the same object multiple times with different arguments in a single API call, this attack is not as easily detectable as the usual brute force attack. This is because normally brute-force attacks utilize a massive number of requests. Here is an example of query batching:
In this example, the ‘systemDiagnostics’ operation (or object) is being queried multiple times with different values passed in the arguments for individual queries. This attack will likely bypass any existing rate limits in the application and will assist the attacker significantly in enumerating a large number of objects. To mitigate this type of attack, it is recommended to prevent batching for sensitive objects and implement object request rate-limiting in code.
Denial of Service
In GraphQL, query depth limitation is disabled by default, hence nested queries of massive depth can be executed to cause a denial-of-service attack on the GraphQL service. Because of the nature of the GraphQL query language, multiple queries can be nested one inside the other (refer to the image).
In GraphQL, when object types reference each other, it is often possible to build a circular query that grows exponentially to a point it could bring the server down due to resource exhaustion. In the example shown above, the application offers two object types, namely Owner and Paste, which reference each other (an owner has a paste, and a paste has an owner), permitting a recursive query to be carried out successfully.
Setting a max_depth for queries can help mitigate this type of attack. The max_depth functionality is the maximum level of depth allowed for a query, ensuring deeply constructed queries will not be accepted by GraphQL.
If you would like to delve deeper into this topic, here are some recommended resources:
Author,
Akshay Khilari
Attack & PenTest Team
Varutra Consulting Pvt. Ltd.
Introduction In the era of digitalization, data security has become a paramount concern. Every day,…
I.Introduction Bluetooth has become an integral technology for billions of smartphones, computers, wearables, and other…
I. Introduction In today's ever-evolving cybersecurity landscape, staying ahead of adversaries has become a challenge.…
Introduction In an increasingly interconnected world, the financial industry is becoming more vulnerable to cyber…
Introduction In today's interconnected world, where smartphones are an extension of our lives, ensuring the…
Introduction Unseen and unpredictable, zero-day threats loom as a constant menace to modern businesses. Detecting…