The State of GraphQL Security in 2024

The State of GraphQL Security in 2024

Posted in

GraphQL is a very popular paradigm for APIs requiring complex interaction and variable surfacing, and for a good reason — it is perhaps the most powerful tool for complex syntactic interconnective APIs, powering everything from social media to next-generation banking.

While GraphQL is very popular, it also has some significant drawbacks, many of which are poorly understood. A recent report from Escape has laid these risks bare. Below, we’ll look at the key findings underpinning this report to gather an understanding of the state of GraphQL security in 2024.

Escape’s Findings

In their research, the Escape team enumerated 160 public GraphQL services, running over 3,800 operations across the corpus. They ran 116 proprietary tests across these queries, with 100 specifically targeted for GraphQL. The findings are broad, but Escape discovered over 13k issues, 4.4k exposed GraphQL secrets, and more than three times the detected issues than their research in 2023.

This data points to a pretty stark conclusion: GraphQL has some severe issues in practical application. This needs to be addressed, especially since Gartner predicts over 60% of enterprises will use GraphQL in production by 2027.

Unrestricted Resource Consumption

Although Escape found vulnerabilities across all the OWASP Top Ten in their findings, many GraphQL vulnerabilities seem to be focused on a specific type of vulnerability: uncontrolled resource consumption. This vulnerability is a fundamental risk present in the very nature of GraphQL. Since GraphQL is meant to surface as much information as the user requests, it is very verbose. In practice, this is seldom addressed and, in fact, is a big concern for most production environments.

In Escape’s testing, 69% of the API services tested had issues related to this category. Beyond issues of denial of service (or distributed denial of service), this also introduces fiscal considerations. Without resource control, an expensive compute bill can rack up, especially in the reality of the modern cloud. For many providers operating a lean stack, depending on cloud services without stringent controls over resource allocation could easily lead to a huge spike in cost that could undermine a business.

Security Misconfiguration

Of course, one of the most common risks with GraphQL services is typical with any tech stack: misconfiguration. Default settings are meant to be a starting block by which developers and providers change and develop their posture. However, too often, they are implemented as-is, introducing a bare-bones and usually incomplete security posture. The dangerous part is that providers frequently get a false sense of security from this effort, thinking they are much more secure than they actually are.

In Escape’s tests, 11% of the tested services had issues with configuration. GraphQL is very verbose and descriptive, and unfortunately, this means that even small gaps can be used to exfiltrate a large amount of data. When this data is improperly secured or encrypted, this can lead to scraping and a fundamental lapse of security. In fact, during their testing, more than 4,000 secrets were exposed in the GraphQL API responses. This exposure included passwords, credit card data, and even access tokens, which could potentially be misused in replay attacks.

GraphQL-Specific Issues

As noted above, GraphQL has some intrinsic faults that are part and parcel of the technology. Its verbosity, its strong user control over queries, its linked context, all of what GraphQL is — and what makes it possible — is also a potential landmine in poor security environments. In Escape’s research, 13% of tested APIs presented GraphQL-specific vulnerabilities in its language and framework.

Given the rapid adoption of GraphQL, this is a clear signal that, despite its popularity, GraphQL is still seldom understood at its foundational level. Providers should take caution with GraphQL and understand that what they are leveraging is a racecar, not a bicycle. It’s incredibly powerful but also incredibly dangerous.

Some of these GraphQL-specific issues include:

  • Over-verbosity, which can expose information that is either private or useful in combination with other data for attacks.
  • Timeout issues stemming from overly complex or detailed requests, whether on purpose or accidental.
  • Depth limit and field limits issues, where users can force an error by taking advantage of the permissive nature of GraphQL querying to overload the system.
  • Schema issues: everything from orphaned objects to type configuration errors can cause GraphQL queries to multiply the vulnerabilities in question, adding error to error until the system is filled with a veritable flood of errors.
  • Exposure of underlying logic and systems can happen due to contextual inference, suggested types and meta contextual data, and other benefits of GraphQL providing a greater overview of the system at-a-glance.

Mitigating Security Issues in GraphQL

Luckily, there are some solid tactics software providers can adopt to improve their GraphQL posture. Some of these were highlighted by Escape, while others have been discussed at length on Nordic APIs.

Validate, Sanitize, and Throttle

As a solid first step, providers should seek to validate and sanitize inputs. Much of the issues noted with GraphQL come down to having overly permissive policies around querying. While GraphQL is designed to be permissive and powerful, there’s no reason someone should be requesting the same resource 50 times in a single query or repeatedly (as in thousands of times) over a one-minute span.

Accordingly, validation and sanitation can make considerable inroads to securing your system. Ensuring each request is well-formed and reasonable will stop 90% of invalid request attacks. From here, throttling through rate limiting or other means will help protect your resources.

The balance here is to be permissive enough that the core GraphQL functionality is preserved, but not so permissive that the system is exposed to damage. It’s a hard balance to hit, but it’s worth considering if you want a truly secure GraphQL implementation.

Remove Dead Code and Audit Often

Another huge fix you can implement is to remove dead code and audit your existing code often. Using tools to control graphs and variants, in addition to detecting and remediating zombie or shadow APIs, can help remove potential attack vectors that you may be unaware of. For those endpoints you are aware of, constant scanning and auditing code for overly permissive or exposed data is a must. Even the best security posture will always have some sort of gap, and assuming you have a perfect posture is always the step right before a major security lapse.

Note that this is not just relevant to the data itself. Function-level authorization, access control, roles, and more should also be routinely reviewed and audited, as these can change with time, introducing new vulnerabilities that can topple even the most secure stronghold in minutes, Ensure proper authorization and authentication is in place, and review it often to make sure it stays in place!

Operate With Estimates

GraphQL is not an all-or-nothing endeavour. In many cases, you can operate in a gray area by adopting some basic tools. Graphql-armor is a package suggested by Escape that can limit requests based on the resource cost and, with some proper cost estimates, can go a long way towards ensuring only proper requests are made. Network timing, token duration over an average useful timeline, and even heuristics based around the highest use during specific times of the day — all of these data points can help you make a more nuanced security posture based in reality instead of best-case scenarios.

This also is true of depth limiting and throttling. By testing what the core function looks like in regular practice and then blocking this in production, you can ensure that real users can use your services while preventing runaway costs, expensive queries, or even queries that go a bit too deep, suggesting some sort of introspection hunting or drive-by targeting. At the end of the day, the more info you have, the more secure you can be.

Question Everything

We get it: you built the system, and you’re quite proud of it. But, look at every decision that has been made and every posture choice and question whether or not it makes sense. Do users really need this much control? Should you really be that permissive? How likely is it that a user will make 200 requests in a single minute?

These questions should be asked because the assumptions made at the start of creating a security posture almost always result in major security issues. Question the posture, and assume that even your average user is a potential attack vector. After all, not all damage to the API is intentional, and sometimes, the worst attacks are by people who mean well but don’t understand the system they are using. Assume that everyone is a threat, and consider the minutia of how you respond to every use case.

Final Thoughts on GraphQL Security in 2024

Escape’s work here is invaluable, as it exposes the underlying issues inherent in GraphQL. Thankfully, there are some security best cases that anyone can deploy at scale to make their system more secure, even if that system is a complex GraphQL implementation.

What do you think of Escape’s research? Are there other methods for securing GraphQL that we missed? Let us know in the comments below!