Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

ESCT: Part 4 - GraphQL Security

modules/4-graphql.livemd

ESCT: Part 4 - GraphQL Security

Mix.install([
  {:grading_client, path: "#{__DIR__}/grading_client"}
])

:ok

Introduction

GraphQL is a query language used to interact with and retrieve data from an application’s data sources. Its structure is designed for flexible and precise queries that efficiently interact with complex, highly nested data sets. Using GraphQL, information is retrieved by stepping through data as if it were arranged as a group of connected nodes instead of a strictly hierarchical set up. Think more of a labyrinth than a tree.

Since GraphQL can be implemented as a component of an application’s API, there are security issues common to all APIs present, as well as concerns related to characteristics of the query language itself. This module will highlight several security issues associated with GraphQL and recommendations for how to address them.

Table of Contents

Disabling Introspection

Description

Introspection queries are a way of enumerating a particular GraphQL implementation to discover details about the queries supported, data types available, and other information. This includes mutation names, fields specific to an organization or dataset, query parameters, and types of objects in the data source. Obtaining this information can help a user, including a malicious one, deduce and discover specifics about the data being stored.

If you are familiar with databases, this is similar to gathering info on the database schema that includes information about table names, fields, database, structure etc.

Malicious actors in their information gathering/reconnaissance efforts can leverage this information as they look for ways to attack your application and construct malicious queries and requests to expose and compromise data.

Excessive Data Exposure is number 3 on OWASP’s API Security Top 2019 and APIs with this issue return too much and/or sensitive information in response to incoming requests and queries. Although it provides a useful function for GraphQL developers, the information returned by introspection can help facilitate attack.

Prevention

The less an attacker can learn about your system or application, the more difficult (though, of course, not impossible given time and resources) it will be to identify vulnerablilities and craft exploits that could result in a successful compromise.

Taking every opportunity to add a layer of difficulty (see defense in depth section in Module 3) for malicious actors is one aspect of securing data and applications.

Imagine trying to surprise a friend who lives in another part of the country with a complete home makeover. You’ve never been to their place but imagine trying to make arrangements, in secret, without having a map to their city, knowing their address, having access to a website with a street view, or having the floorplans. What if they live on the 30th floor of an apartment building, there’s no street parking, and they have 4 large pet dragons?

Since introspection queries provide the floorplans to your data, one step in making an attacker’s job more difficult is to, if an evaluation of your application development processes determines it is not needed, disable introspection. If it is not possible to completely disable introspection, the next best defense is to limit access, by following least privilege, or implement other controls to limit exposure. Please see references for more details.

Example

Vigil is an elixir package that when added to your application’s dependencies, can intercept incoming GraphQL introspection requests and return an error/forbidden message to the client, instead of information about the schema.

It can also intercept responses to ensure no schema data is being leaked in any error messages shown to the client.

Resources

  1. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/12-API_Testing/01-Testing_GraphQL
  2. https://cybervelia.com/?p=736
  3. https://github.com/podium/vigil

Quiz

Which of the OWASP API Security Top 10 2019 issues does disabling introspection queries address?

Uncomment the line with your answer.

# answer = :API6_2019_Mass_Assignment
# answer = :API10_2019_Insufficient_Logging_Monitoring
# answer = :API3_2019_Excessive_Data_Exposure
# answer = :API4_2019_Lack_of_Resources_Rate_Limiting

IO.puts(answer)

Error Disclosure

Description

When an application responds with overly verbose error messages, it runs the risk of providing vital information to an attacker seeking to exploit the service. It is a best practice to limit the amount of meaningful information that gets sent back to any user in the event there is an issue with a service, or other application component, including APIs.

Within the context of a GraphQL implementation, when errors occur, the server could send error messages that reveal internal details, application configurations, or data which could be used to further an attack on the application.

Prevention

Any errors disclosed from the server and displayed to the user should be limited- boring is good when it comes to error messages displayed to users!

OWASP recommends explicitly defining and enforcing all API response payload schemas including error messages; one might be able to accomplish this in an Elixir GraphQL context through the use of Absinthe.Middleware.

Quiz

Select the best example of a “good” error message, from the perspective of developer who is writing code that is intended to inform a user (who may or may not be a malicious actor) that the action they have attempted was unsuccessful:

Uncomment the item number (1-4) with your answer

# -------------------------------------------------------------
# answer = 1
#
# HTTP/2 401 Unauthorized
# Date: Tues, 16 Aug 2022 21:06:42 GMT
# …
# {
# 	“error”:”token expired”
# {
# -------------------------------------------------------------
# answer = 2
#
# HTTP/2 200 OK
# Date: Tues, 16 Aug 2021 22:06:42 GMT
# …
# {
# 	“errors”:[
# 		{
# 			“locations”:[
# 			{
# 				“column”:2,
# 				:line”:2
# 			}
# 			],
# 			“message”: “Parsing failed at
# 		}
# 	]
# }
# --------------------------------------------------------------
# answer = 3
#
# HTTP/2 200 OK
# Date: Tues, 16 Aug 2022 21:06:42 GMT
# …
# {
# 	“error”:”ID token for user 55e4cb07 at org 1234 expired”
# {
# ---------------------------------------------------------------
# answer = 4
#
# HTTP/2 404 File Not Found
# Date: Tues, 16 Aug 2022 21:06:42 GMT
# …
# {
# 	“error”:”/www/home/file.txt not found ”
# {
# ---------------------------------------------------------------

IO.puts(answer)

Resources

  1. https://github.com/OWASP/API-Security/blob/master/2019/en/src/0xa7-security-misconfiguration.md
  2. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/12-API_Testing/01-Testing_GraphQL
  3. https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html

Resource Exhaustion

Description

When building an application, it is necessary to manage the access and use of all relevant internal and external resources involved in the context of the application. This will help ensure the continued availablilty of the application and its functionality for all legitimate users and entities.

Resource exhaustion occurs when memory, processes handling application requests, network traffic transmissions, server capacity, storage, and other host operating system or device limitations are exceeded while an application is running. When resource allocation is not well managed, applications become vulnerable to negative impacts in performance, unintentional service failures, and denial of service attacks, in which a malicious actor takes advantage of resource limitations to intentionally overwhelm and crash a system.

Resource exhaustion can occur inadvertently through legitimate use or could be triggered intentionally in a DoS attack by a malicious actor who sends a large number or resource intensive requests to overload the application.

The structure of GraphQL queries make it particularly succeptible to this type of attack as they can be crafted to perform long running and extensive operations, depending on the data being queried.

In addition to strategies like rate limiting to protect APIs in general, another approach to protecting GraphQL from resource exhaustion involves anticipating the cost of a query and allocating resources based on known available capacity. The next section introduces this approach.

Cost Theory

Description

Resource intensive queries, like those where a GraphQL query tries to traverse and then return a significant amount of highly nest data can cause a server/service to expend a significant amount of it’s processing power and other resources. These high cost queries can render a server and therefore the application useless.

One approach for implementing validation on incoming queries to determine their “cost” in terms of the resources the use. Queries are defined by how much load they place on the server/service processing the request, allowing developers to plan for how best to manage resources. This is a little like making a budget.

This approach also helps implement rate limiting by establishing a query cost based on the type, operation, and expected performance of each unique GraphQL request for data, and by anticipating the load on the server.

Resources

  1. https://shopify.engineering/rate-limiting-graphql-apis-calculating-query-complexity

<- Previous Module: Secure SDLC Concepts || Next Module: Elixir Security ->