Introduction
GraphQL was developed and open-sourced by Facebook to facilitate the data-fetching process. It is an API query language that can be used as an alternative to REST. GraphQL is gaining popularity for implementing and consuming APIs due to the numerous advantages it offers. One advantage is that it allows users to specify exactly what they need from a data source. This, in turn, solves the issue of data under-fetching and over-fetching since only the needed/requested data is retrieved. Another benefit is that it allows users to fetch multiple objects using a single request (a GraphQL API has a single endpoint). This is different to RESTful APIs which often offer multiple endpoints; meaning that for different data fields (objects) users would potentially need to send multiple requests to multiple endpoints. GraphQL reduces the number of round-trips in comparison to REST, thus, improving efficiency in terms of bandwidth usage (bandwidth savings).
Security Attacks
GraphQL is susceptible to a number of security vulnerabilities that may be exploited by malicious agents (e.g., performing passive or active attacks).
The Open Web Application Security Project (OWASP) has defined five common security attacks that GraphQL APIs are susceptible to:
- Injection: It is one of the most common web application attacks. It is amongst the oldest, yet most dangerous. In an injection attack, a malicious agent injects a malicious code into a query. This code gets processed by the program/application as part of the received query. As a result, the program/application is tricked into performing a function it is not supposed to do or revealing information it is not supposed to disclose. Some examples of injection attacks are SQL, NoSQL, cross-site scripting (XXS) and OS command injection. For instance, in an SQL injection attack, a malicious agent may inject a code into an SQL query (e.g., ‘OR 1=1’) to retrieve the entire data in a database (e.g., since 1=1 is always true, all entries in a database will be returned).
– REST APIs: Susceptible.
– GraphQL APIs: Susceptible. - Denial of Service (DoS): A DoS attack occurs when a malicious agent sends a large amount of requests to overwhelm a network resource (e.g., servers, devices, machines, etc.) rendering it unreachable by other users trying to access this resource (unavailable). GraphQL has no limits on the number of incoming requests per user or per IP address. GraphQL also enables users to combine multiple requests into one (single roundtrip) and retrieve multiple objects from different data sources. Theoretically, these requests can include an unlimited amount of object fields, organized in a nested structure. There are no rules on the (nest) depth limit and the complexity of the incoming requests. As a result, DoS attacks may occur either due to the large amount of requested data in a single request or due to a large number of incoming requests (e.g., CPU exhaustion).
– REST APIs: Susceptible.
– GraphQL APIs: Susceptible. - Broken authorization: It is the improper implementation (or absence) of authorization checks. As a result of broken authorization, an authenticated user may receive a valid response upon sending a request that includes the resource ID of another user (unauthorized access to resource). Not only does broken authorization lead to information leakage but it can also enable malicious agents to modify sensitive data (e.g., personal information, passwords, bank pincodes, etc.) and/or perform unauthorized actions (e.g., make financial transactions on behalf other users). This is referred to as Broken Object Level Authorization (BOLA), previously known as Insecure Direct Object Reference (IDOR). In GraphQL, two or more object types may be interdependent (schemas are often cyclic data graphs), hence, one might be able to access the same data resource in a direct and indirect manner. Authorizing users against all requested objects is mandatory, but generally absent, in GraphQL.
– REST APIs: Susceptible.
– GraphQL APIs: Susceptible. - Batching: It is a form of brute force attacks and it occurs as a result of a GraphQL feature. As mentioned previously, GraphQL enables users to send multiple request in one network call. Consequently, a malicious agent may send the same request multiple times, but with incremental input values (for example, if the input is of type integer). Eventually, this would lead to a successful brute force attack and even a DoS attack if the number of sent requests is large.
– REST APIs: Not susceptible to batching since it is a GraphQL feature, but susceptible to brute force attacks.
– GraphQL APIs: Susceptible. - Insecure default configurations: GraphQL has a number of default settings/configurations that introduce security risks and vulnerabilities. Introspection and excessive errors are two examples of such insecure configurations. Introspection allows users to query the GraphQL server for information about the API (schema). This includes data structures, mutations and fields (which sometimes can be private). GraphQL also returns field suggestions when input field values are incorrect, and highly descriptive and detailed errors, both of which reveal (sensitive) information that might be useful and exploited by attackers (excessive data exposure).
– REST APIs: Not susceptible.
– GraphQL APIs: Susceptible.
While some of attacks are not new such injection and DoS attacks, others are specific to GraphQL such as batching attacks and insecure default configuration-related attacks. GraphQL offers new features to improve the user and developer experiences, however, these extensions introduce new security vulnerabilities to GraphQL APIs that weren’t present before (in addition to the classical API security vulnerabilities).
Security Recommendations
For securing GraphQL APIs and limiting the occurrence of previously disscused attacks, several measures can be adopted:
- Input validation and sanitization: Input validation is typically implemented to check the input against defined policies and criteria (input compliance). On the other hand, input sanitization, modifies/cleans the input so that unwanted/unsafe characters are removed/filtered.
– Attack averted: Injection. - Access control: By default, GraphQL does not check the permissions of users requesting objects. This may lead to unauthorized data disclosure and in some cases unauthorized modification of data. To overcome this issue, access control lists (e.g., role-based) can be created and enforced to associate users to their objects. Also, it would be useful to allow users access to specific data fields rather than allowing all users access to all available fields. When using GraphQL, authorization should be implemented for every requested object type and field (which can be interdependent), rather than validating the authorization checks once every request, which is the case for REST APIs.
– Attack averted: Broken authorization. - Secure configurations: Two of GraphQL’s insecure default configurations include excessive errors and introspection. The issue of excessive errors can be solved by customizing the errors returned by GraphQL APIs. With regards to introspection, this feature can be disabled for all users except those who are authenticated.
– Attack averted: Insecure default configuration-related attacks. - Depth, amount and rate limiting: These three techniques are used to limit the size of incoming requests and their number. Depth limiting limits the depth of the request (number of levels/nests within the request), whereas amount limiting limits the number of requested/returned objects per request. Rate limiting limits the number of incoming requests per user or per IP address.
– Attack averted: DoS and Batching attacks.
Conclusion
GraphQL is a new API language that is gaining a lot of interest and adoption due to its simplicity, dynamicity and flexibility. It is changing the way we view, build and consume web applications. But with every new technology, new challenges unravel. GraphQL is prone to both, classical API vulnerabilities and new vulnerabilities specific to this technology. Existing solutions can be implemented to overcome some GraphQL’s vulnerabilities. Other vulnerabilities may require extensions and adaptations. Securing GraphQL remains an active research topic.