GraphQL DOS
This Section focuses on how GraphQL's query language can be exploited to cause denial-of-service (DoS) attacks, which can degrade performance or completely take down a server.
DoS Vectors:
Circular Queries (Recursive Queries): These occur when relationships in the GraphQL schema create bidirectional links between objects, leading to recursive requests that can crash a server.
Vulnerable code
Exploit
Circular Introspection Vulnerabilities:
The introspection system has its own schema, defined in the official GraphQL specification document.
GraphQL's built-in introspection system may contains a circular relationship that can be exploited when introspection is enabled. This circularity arises from the system's schema:
Schema Structure:
The
__Schema
type has atypes
field referencing[__Type!]
(non-nullable array of__Type
objects).The
__Type
type includes afields
field returning[__Field!]
(non-nullable array of__Field
objects).The
__Field
type has atype
field referencing__Type
, creating a circular dependency between__Type.fields
and__Field.type
.
Testing the Circular Query: The circular relationship can be tested with a query like this:
Exploitation Risk: While a single query may not disrupt a server, a series of complex circular queries could degrade performance or potentially crash the system.
For further details, refer to the full introspection schema in the GraphQL Specification.
Field Duplication:
By repeating the same field multiple times in a query, an attacker can force the server to process the same information repeatedly. Although GraphQL will consolidate the response, the server will still process the request multiple times, resulting in resource exhaustion.
GraphQL may seem to ignore repeating fields due to response consolidation. When you query with repeated fields, like in Listing 5-5 with content repeated five times, GraphQL shows only a single content field in the response. However, server-side vulnerabilities can still arise unless defenses like query cost analysis are used.
Alias Overloading
GraphQL aliases can be exploited to send multiple requests with different names in a single query, which can overwhelm the server.
Chaining Aliases and Circular Queries:
Directive Overloading: Similar to field duplication, this involves sending many directives with a query, exhausting the server’s query parsers.
Exploit Script: The script multiplies a directive (e.g.,
@dos
) to create a malicious payload, sends it in a query, and runs 300 threads in an infinite loop to overload the server.Usage: Run with the command:
Impact: The server may become slow or unresponsive during the attack.
Note: The directive (
@dos
) can be any arbitrary text.
Circular Fragments
Fragments that reference one another can cause infinite loops, leading to DoS conditions.
Object Limit Overriding
Overriding limits on fields that return arrays, by using API pagination arguments like filter
, max
, limit
, and total
, can result in DoS.
GraphQL servers often limit the amount of data returned to clients, especially for fields returning arrays, to prevent excessive load. However, these limits can sometimes be overridden, posing potential risks.
Default Limits: Without explicit limits, queries (e.g.,
pastes
) may return all records. For example, a database with 10,000 objects could overwhelm server and client resources.Server Logic: Servers can enforce limits, such as returning only the most recent 100 items, through sorting or filtering at the GraphQL or database level.
Override Example: Clients may bypass limits using arguments like
limit
:This might execute as:
Pagination: Keywords like
limit
,offset
,first
, andlast
are common for managing large datasets. Pagination splits data into smaller chunks for efficient querying.Risks:
Large datasets could enable database-level DoS if the server processes excessive rows.
Introspection or trial queries can reveal supported arguments, enabling abuse.
Mitigation: Enforce strict server-side limits and implement robust pagination to protect against excessive data requests.
Array-Based Query Batching:
This technique involves sending multiple queries within a single HTTP request using arrays. This can bypass traditional rate-limiting controls and exacerbate the impact of other DoS vectors.
Detecting Query Batching by Using BatchQL:
BatchQL was able to detect that both array-based batching and alias- based batching are available.
Testing for DoS Vulnerabilities:
Manual review of SDL files: Developers should look for circular relationships in the schema, or they can use GraphQL Voyager to visualize the schema.
Using Schema Definition Language Files: Example: https://github.com/dolevf/Black-Hat-GraphQL/blob/master/ch05/sdl.graphql
Using GraphQL Voyager:
InQL:
GraphQL Cop: This tool can detect DoS vectors by auditing the GraphQL API and schema.
Denial-of-Service Defenses in GraphQL:
Query Cost Analysis: Assigning costs to fields to limit the overall cost of a query.
Query Depth Limits: Limiting the number of nested fields in a query.
Alias and Array-Based Batching Limits: Restricting the number of aliases or batched queries allowed in a single request.
Field Duplication Limits: Limiting the number of duplicated fields in a query.
Limits on the Number of Returned Records: Limiting the number of records returned by a query.
Query Allow Lists: Only allowing pre-approved queries to be executed.
Automatic Persisted Queries (APQ): Using a server-side cache of approved queries to avoid the need to parse every request.
Timeouts: Setting time limits for query executions.
Web Application Firewalls (WAFs): Using a WAF to detect and block malicious requests.
Gateway Proxies: Merging multiple GraphQL schemas into one, and enforcing policies at the gateway.
Last updated