Best Practices For Graphql Security
Published: 2021-11-25 15:50:52

Being one of the most popular query languages, commonly found vulnerabilities make GraphQL Security a topic of consistent deliberation, assessment, and flaw mitigation. In this blog post, we delve into various GraphQL vulnerabilities, best practices to mitigate risks and address some commonly asked questions. 

## What is GraphQL?

GraphQL is a server-side runtime, API query language that prioritizes returning only the data that 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 alternative to the REST API framework. The language can be deployed within an Integrated Development Environment (IDE) and provides a syntax that describes how users should ask for data. GraphQL offers a framework that operates predictably while allowing developers to build APIs with their chosen methods. 

## What is GraphQL Security?

With its feature-rich platform that simplifies the creation of API queries, GraphQL is now considered a critical component in developing modern application tech stacks. While it enables the creation of flexible APIs, GraphQL is considered prone to allow malicious queries that compromise application servers.

To help organizations reduce attack surfaces on GQL APIs, there are certain considerations that help mitigate security issues inherent to GQL platforms. These include:

### Insufficient validation for custom scalars

When using GraphQL, raw data is represented by the scalar type. GraphQL APIs typically support five basic scalar data types: **Int, Float, Boolean, ID,** and **String**. While this basic set is enough for simple APIs, GraphQL allows developers to craft their own scalar types for APIs that require additional raw data types. If developers choose to do this, they should configure additional user input validation and sanitization processes. Failure to implement these functions compromises GraphQL’s scalar-type safety.

### REST Proxies act as API attack vectors

When adapting existing APIs to be used by GraphQL clients, developers typically implement GraphQL as a thin proxy layer on top of an internal REST framework. If this transition is implemented without adequate security considerations, a malicious user can modify the path or parameters specified in API requests. When the modified requests are parsed to the backend API, attackers can carry out cross-site request forgery.

### Authorization flaws

GraphQL leaves the responsibility of configuring authorization and authentication checks on the implementor. The GraphQL API includes multiple authorization checks in both query-level resolvers and those that load additional data. When authorization is handled directly by query-level resolvers, any unchecked API instance presents an attack surface. As the API schema increases in complexity, so does the [risk of attackers exploiting](https://crashtest-security.com/7-signs-that-your-website-has-been-hacked/) this flaw. 

### Introspection Queries may expose sensitive data

Some developers implement ‘hidden’ API endpoints that cannot be publicly accessed. This could be done for API endpoints that enable communication between the GraphQL server, or for hidden administrative functionality. GraphQL includes an introspection feature that makes it easy to access these endpoints without proper authorization. The introspection feature allows clients to access information about GraphQL schema. In the eventuality of an attack, introspection queries can be used to access private information about API configuration and other clients.

### Rate limits are hard to implement

GraphQL APIs are inherently complex since each query can take multiple actions, requiring extensive server resources. Thus, using the default rate-limiting strategy by capping the number of [HTTP](https://crashtest-security.com/what-is-tls-ssl-http-and-https-and-how-do-they-work-together/) requests received is not sufficient. If there is a loop between two object types, attackers can craft abusive queries that make execution increasingly complex. This strategy can be used to orchestrate a **denial-of-service** attack on GraphQL applications.

## Common Graphql Vulnerabilities

While GraphQL offers flexibility in building APIs, it involves complex configurations that may expose applications to security vulnerabilities. Failure to address these vulnerabilities exposes attack surfaces that malicious actors could use to access the API layer. Following are some common GraphQL vulnerabilities.

### GraphQL Batching Attacks

The GraphQL framework supports introspection query batching – the ability to send multiple requests to the backend API in a single call. This is useful for reducing the overhead of API requests since it reduces the total number of server round trips. A hacker could use the query batching feature to orchestrate a brute force attack by repeatedly loading data from the API server or database. The attack enables the hacker to perform rapid, undetectable exploits. 

Following is a typical example of a batched GraphQL query searching for different instances of a Digital Record Object Identification (DROID) object:

```
query {
  droid(id: "2000") {
    name
  }
  second:droid(id: "2001") {
    name
  }
  third:droid(id: "2002") {
    name
  }
}
```
A hacker can enumerate every droid object in the API server by crafting a few network requests. This may lead to API-level DoS attacks, brute-forcing secret data, bypassing request rate limits, and object enumeration among other security issues.

### GraphQL Injection Attacks

GraphQL APIs typically connect with a Database Management System as the data source. Once the Resolver at the backend of the API receives a request, the queries are distinguished based on operation sets. The Resolver queries the database, then fetches data accordingly if the operation involves data extraction. If data from the API client is trusted without proper sanitation, hackers can orchestrate an [SQL/NoSQL injection attack](https://hackerone.com/reports/435066). In case of inadequate input sanitization, attackers can also perform other [forms of injection attacks](https://crashtest-security.com/sql-injections/), such as LDAP injection and [command injection](https://crashtest-security.com/command-injection/). 

### GraphQL CSRF attacks

A [Cross-Site Request Forgery (CSRF) attack](https://crashtest-security.com/cross-site-request-forgery-csrf/) forces the webserver to run unwanted actions without the legitimate user’s knowledge. When CSRF vulnerabilities are present, attackers send authenticated requests within the context of a currently logged-in user. GraphQL applications are susceptible to CSRF attacks since the APIs receive browser requests that automatically accept all cookies, including session cookies.

There are primarily two types of GraphQL CSRF attacks: **Post-based CSRF** and **Get-based CSRF**.

Most attackers typically target POST requests since they affect the state of GraphQL applications. GraphQL uses multiple API layers to translate multi-format incoming requests, making the applications susceptible to CSRF. Some developers also forego the implementation of CSRF controls. This is because they assume that GraphQL API endpoints are invulnerable to CSRF since they only accept Content-Type headers set to *application/json*.

For instance, the following POST request can be used to issue a valid GraphQL query:

```
POST /graphql HTTP/1.1
Host: redacted
Connection: close
Content-Length: 100
accept: */*
User-Agent: ...
content-type: application/json
Referer: https://redacted/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: ...

{"operationName":null,"variables":{},"query":"{\n  user {\n    firstName\n    __typename\n  }\n}\n"}
```
The server could accept this request as a *form-urlencoded* POST request:

```
POST /graphql HTTP/1.1
Host: redacted
Connection: close
Content-Length: 72
accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: https://redacted
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: ...

query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
Experienced attackers can also potentially convert this into a CSRF attack surface by using an automated scanning tool:

```
<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://redacted/graphql" method="POST">
      <input type="hidden" name="query" value="&#123;&#10;&#32;&#32;user&#32;&#123;&#10;&#32;&#32;&#32;&#32;firstName&#10;&#32;&#32;&#32;&#32;&#95;&#95;typename&#10;&#32;&#32;&#125;&#10;&#125;&#10;" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
```
## Checklist – Prevent Graphql vulnerability

Given the power and flexibility offered by GraphQL, it is important to mitigate security issues proactively. This checklist explores some GraphQL security best practices. 

### Preventing GraphQL Injection attacks

For applications that handle input to be processed by a secondary interpreter, such as LDAP, ORMs/SQL/NoSQL, or [XML](https://crashtest-security.com/xxe-processing/) among others, it is recommended for developers to ensure the following:

* Choose libraries that provide safe APIs, such as parameterized statements

* Escape or Encode input according to the chosen interpreter’s best practices

It is also important to follow the chosen module’s documentation for appropriate use of the tool. Most languages and frameworks have encoding/escaping functionality built-in, as a result, it is important to understand the core functionalities and choose the one that suits their use case.

### Preventing DoS Attacks

DoS attacks are aimed at making the GQL API slow and unresponsive. Some methods to prevent these attacks include:

* Implement **depth limiting** for incoming GraphQL queries
* **Add timeouts** for both the infrastructure and API layer
* Perform **query cost analysis** to limit expensive queries
* Enforce **rate-limiting** for incoming requests per API client

### Access Control for the GraphQL API

To secure access to the GraphQL API, developers should:

* 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

### General GraphQL API 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

## FAQ’S for Graphql Security

### How prevalent are API attacks?

The growth of APIs has increased the number of attempted attacks that rely on automated applications executing malicious actions through the Application Programming Interface. According to a report by wallarm.com, [malicious bots make up to 20% of the internet](https://www.zdnet.com/article/bad-bots-focus-on-financial-targets-make-up-20-percent-of-web-traffic/) as of 2019. This makes securing APIs a critical part of application security measures. 

### Are there tools that simplify GraphQL security?

There are a variety of open-source projects that simplify the creation and management of GraphQL APIs. These include Apollo client, Offix, Graphback, and OpenAPI-to-GraphQL. 

### How does GraphQL handle authentication and authorization?

GraphQL is a server-side runtime query language, hence it doesn’t handle authorization logic. However, the platform allows developers to implement authentication and authorization checks in the business logic layer before exposing the API to clients.

**Crashtest Security Suite** helps you [detect application vulnerabilities](https://crashtest-security.com/how-to-find-vulnerabilities/) by implementing a security vulnerability scanner that provides accurate reports and remediation advice. The continuous, automated vulnerability scanning process allows developers to save time and focus on work while it benchmarks the web app against [OWASP top 10](https://crashtest-security.com/owasp-top-10-2021/) to enhance security posture. The suite integrates with most existing development stacks and allows you to scan various web applications, Javascript functions, and APIs in minutes.

Try Crashtest Security today to discover how it integrates into your development stack for efficient, automated vulnerability scanning.

*This article has already been published on https://crashtest-security.com/graphql-security-vulnerabilities/ and has been authorized by Crashtest Security for a republish.*

*Featured Image Courtesy – Photo by Joshua Aragon on Unsplash*