GraphQL was created and developed with flexibility in mind: clients should be given the power to ask for exactly what they need and nothing more. Much of this flexibility involves allowing customers to execute multiple queries in a single request, request multiple objects also in a single request, and ask for nested objects (e.g., users and their blog posts). In this article, we will discuss how the latter can be exploited, leading to Denial of Service (DoS).
If you don't know the Damn Vulnerable GraphQL Application, then check it out: "Damn Vulnerable GraphQL Application is an intentionally vulnerable implementation of Facebook's GraphQL technology, to learn and practice GraphQL Security". We will use it to illustrate Deep Recursion Query Attack.
The Damn Vulnerable GraphQL Application supports two types, namely Owner and Paste, which reference each other:
The figure above illustrates the relationship between Paste and Owner: “Paste has Owner”, but we should also expect it to work the other way around: “Owner has Pastes”. We can confirm it, updating the original query and requesting the owner‘s pastes, as shown in the figure below:
Now, the getPastes query first lists the pastes (depth 1) and for each paste includes the owner’s name (depth 2) and its pastes (depth 3). Of course, this query is redundant, and it doesn’t make much sense, but if you’re wearing your black hat, then you should see where it may lead.
If there’s no security mechanism or optimization in place, we can keep going deeper and deeper, exploiting this relationship. The more nested objects we request, the more time the server should take to fulfill the request and the bigger the response payload will be; thus, more bandwidth is required to transfer it. Going too deep may lead to Denial of Service (DoS).
The table below illustrates the Damn Vulnerable GraphQL Application performance degradation regarding the query depth:
You can read more about “Query Limiting (Depth & Amount)” in the OWASP GraphQL Cheat Sheet or this Apollo blog post: “Securing Your GraphQL API from Malicious Queries”. Most popular GraphQL implementations do not have a security control to prevent deep recursion, or it is disabled by default. Setting a timeout, maximum depth, or a query complexity threshold value should be an easy remediation against DoS.