GraphQL: Securing The NextGen API

Updated: Jul 18

A recent survey of over 23,000 developers by State of JavaScript showed that 86% of developers who have heard about GraphQL APIs want to learn to use them. Their data also revealed a major increase in developer experience with GraphQL from 5% in 2016 to 38.7% in 2019. None of this surprises us at Resilient, as we continually come across software companies that are sold on GraphQL. The question is, how can your business leverage the benefits of GraphQL APIs without being exposed to GraphQL attacks?


Photo by Bruno Thethe from Pexels

First, A GraphQL Primer

GraphQL is an API query language that prioritizes returning only the data that a server's clients request. The language is intended to make APIs lightweight, flexible, developer-friendly, and fast. GraphQL lets development teams craft requests that access data from multiple sources in a single interface call, making it an efficient alternative to the REST API framework. It gives clients the power to ask exactly what they need and makes it easier to evolve APIs over time. A graphQL query can be used to retrieve, insert, and update data in 1 call!


3 Reasons Why You Should Care About GraphQL Security

  1. The potential benefits of GraphQL are great, but the security implications of GraphQL are less understood by most developers. Are there negative consequences of querying flexibility? Which vulnerabilities are easiest for attackers to exploit?

  2. You can query a GraphQL schema for details that completely reveal information about its data structures, including arguments, fields, types, and descriptions. Inadvertently leaking this information can potentially expose additional attack surfaces, which may contain other interesting vulnerabilities for attackers to leverage.

  3. GraphQL offers an Integrated Development Environment (IDE) named GraphiQL (note the i) that allows users to construct queries against a GraphQL endpoint by clicking through fields and inputs in a user-friendly interface. GraphiQL can be used to understand the supported schema of an endpoint and subsequently expose additional attack surfaces, such as what queries or mutations exist. Querying the server in this way could provide the missing piece when trying to construct a complex, high-severity attack.


5 Common GraphQL Security Vulnerabilities and their Mitigation


1. Inconsistent Authorization Checks


Flaws in GraphQL authorization logic are quite common. While GraphQL helps implement proper data validation, API developers are left to implement authentication and authorization methods. Additionally, the multiple “layers” of resolvers typical to a GraphQL API make doing this properly more complicated – authorization checks have to be present not only at the query-level resolvers, but also for resolvers that load additional data (for example, to load all of the posts for a given user.)


For example, with a photo sharing app, there are many ways to retrieve a listing of image objects – a client can retrieve a list of users, then retrieve all their public image, or simply retrieve a photo with a unique ID. For example, the following query might be used to read all of the posts that belong to the currently logged-in user:

query GetImage
{
  # "me" returns the current user
  me {
    # then, resolve the photo
    images {
      # finally, return the content
      # and whether this is a public image or not.
      public
      content
    }
  }
}

But one must realize that the different paths to retrieve an image require their own implementation of logic for verifying authorization. For example, in the code snippet below, there's no authorization when retrieving the image by ID. This allows an attacker to perform a direct object reference attack - by just submitting any ID and retrieving an image, whether public or private.

query GetImage
 {
   # we shouldn't be able to read post "1"
   image(id: 1) {
       public
       content
   }
}

GraphQL's documentation describes how to perform authorization securely. The mitigation is simple – instead of performing authorization logic inside of resolver functions, all authorization logic should be performed by the business-logic layer living underneath. That way, all necessary authorization checks can be performed and tested in one known location.


2. Missing Validation of Custom Scalars

When using GraphQL, a scalar type is a type used to represent raw data. The built-in scalar types are Int, Float, Boolean, String, and ID (which is really just a string). For scenarios where additional raw datatypes are useful, GraphQL allows application developers to define their own scalar types. However, when an API developer implements their own scalar type, they are responsible for building in (and indeed must build in) input sanitization and type validation for all input the API receives for that type, else the custom scala becomes vulnerable to unexpected or crafted inputs.


3. Failure to Appropriately Prevent DOS Attacks

The increased complexity of GraphQL APIs makes the implementation of denial-of-service (DOS) protections more difficult. Whereas one REST API request performs just one action, a GraphQL query can take arbitrarily many actions and consume a lot of server resources. Hence, the rate-limiting DOS protection technique - which restricts the number of server requests - is an ineffective strategy for preventing DOS attacks on GraphQL APIs.


One solution is to limit the number of nested GraphQL queries so that your API rejects long-running queries as well as queries that will return massive results. Another solution is the place a cap on the allowed complexity of the query, such that highly complex queries, which may not be nested, are also rejected. Both of these solutions are natively supported by GraphQL.


4. GraphQL Injection Attacks

GraphQL APIs typically connect with a Database Management System i.e. SQL or NoSQL. If data from the API client is trusted without proper input sanitation, hackers can carry out any injection attacks for which the database (or the software using the database) is vulnerable. Examples are SQL/NoSQL injection, LDAP injection, and command injection.


The solution REST APIs is to sanitize data inputs and test APIs using vulnerability scanning tools like Burp Suite.


5. GraphQL CSRF attacks

A Cross-Site Request Forgery (CSRF) attack forces the webserver to run legitimate actions using a user's credentials (often stored in cookies), without that user’s knowledge. When CSRF vulnerabilities are present, attackers send authenticated requests within the context of a currently logged-in user, by tricking them into clicking on a malicious link. GraphQL applications are susceptible to CSRF attacks since the APIs receive browser requests that automatically accept all cookies, including session cookies.


To mitigate this, the application should implement a sufficiently random CSRF token that must be sent with each client request, and is verified by the server.



GraphQL Security Best Practices

Other approaches that developers can leverage to protect the GraphQL layer include:

  • Use a whitelist for allowed characters

  • Define GraphQL schemas for mutations input

  • Use a single internal character encoding format to properly handle Unicode input

  • Add pagination to limit the amount of information that can be accessed by a single request

  • Validate that the current user has the authority to view/mutate/modify the data as per their request

  • Enforce authorization controls on endpoints and edges

  • Utilize RBAC middleware to enable access control through query and mutation solvers

  • Disable introspection queries in public APIs

  • Disable GraphQL schema exploration tools such as GraphiQL


Reducing the Cost of Security Analysis

In addition to the mitigations and best practices listed above, you should deploy automated vulnerability scanning to reduce the time and cost of GraphQL security analysis for your APIs. Burp Suite with either of the GraphQL Raider or InQL extensions can be used for this purpose.


In Conclusion

The strengths of GraphQL in API querying flexibility and power, coupled with the relative newness of GraphQL experience for most developers can create risks that threaten businesses. Secure design, coding, and testing must be intrinsically embedded into the development of GraphQL APIs, and this is where Resilient shines. We are software security ninjas, uniquely skilled in the strategy for ensuring that APIs and SaaS platforms are secure by design and harder to hack.


Click the button below to learn more about how we can help you and your team.



Artboard 1.png

Find PEACE and REST of mind.

Empower your team to predict and prevent SaaS attacks with our new Secure Design Workshop.

Artboard 2.png

Need strong security for your SaaS business?

We are here for you. Schedule a FREE software security assessment now.