GraphQL 101: Here’s everything you need to know about GraphQL (Part 2)

 

Read Part 1 on GraphQL here.

In last week’s blog we learnt about the basics of GraphQL and how to configure a GraphQL server. We also discussed some key differences between GraphQL and REST API. 

Here’s a brief recap:

GraphQL is an open source query language for APIs that helps to load data from a server to the client in a much simpler way. Comparing multiple aspects of both GraphQL and REST API, we have seen that GraphQL operations are superior to that of REST API. Although the benefits of this open source language is plenty, it comes with security vulnerabilities that developers tend to encounter from time to time. 

Picking up from there, in the second part, we will discuss:

  • GraphQL: Common misconfigurations that enable hackers
  • Testing common misconfigurations in GraphQL

 

GraphQL: Common misconfigurations that enable hackers

GraphQL is one of the most efficient and flexible alternatives to REST API. However, it is vulnerable to the same attacks that REST API is prone to. 

GraphQL depends on API developers to implement its schema for data validation. During this process they could inadvertently introduce errors. In addition to this, new features and functionalities, which meet client requirements, are added to web applications by the hour. This also increases the chance of developers committing errors.

Here we highlight some of the common misconfigurations and issues with GraphQL, that allow hackers to exploit it.

  • Improper Access Control or Authorization Checks

The limitations of the user authentication process can potentially grant unauthorized access to anyone. In the event that the authentication process is defective, the web application fails to restrict access to an object or resource which leads to delivering the data of another user without performing authorization checks. The flawed method allows attackers to bypass the intended access restriction, exposing user data to abuse, deletion, or alteration.

Let’s consider the scenario where a user, with the numeric object ID: 5002, wants to retrieve his/her PII such as email ID, password, name, mobile number, etc. If this user knowingly or unknowingly uses a different user ID (say, 5005), and this ID belongs to another active user, but the search leaks his/ her data, it shows that the GraphQL resolver allows unauthorized access. 

The following query consists of a user ID representing a logged in user and fetches the user’s PII:

 

query userData {

  users(id: 5002) {

    name

    email

    id

    password

    mobileNumber

    authorizationKey

    bankAccountNumber

    cvvNumber

  }

}

 

However, if the same authenticated user is able to fetch the data of ID 5005, that means there is improper access control to an object or resource. It enables hackers/ attackers to access the data of multiple users. It also allows an attacker to perform malicious activities like editing the user’s data, deleting the user from the database, etc.

 

  • Rate Limit Issue and Nested GraphQL queries leading DoS attack

In a single query, it is capable of taking multiple actions in response to multiple HTTP requests. This feature increases the complexity of GraphQL APIs, which makes it difficult for API developers to limit the number of HTTP requests. If the request is not properly handled by the resolver at the GraphQL API layer then it opens a door for actors to attack the API and to perform denial-of-service (DoS) attacks.

To avoid this, only a specific number of requests per minute should be allowed to the API, and in case the number of requests exceeds the limit, it should trigger an error or reject the response.

Let’s look at the following example of such nested queries:

 

query nestedQuery {

  allUsers {

    posts {

      follower {

        author {

          posts {

            follower {

              author {

                posts {

                  follower {

                    author {

                      posts {

                        id

                      }

                    }

                  }

                }

              }

            }

          }

        }

      }

    }

  }

}

 

  • Default introspection system reveals internal information

Some API endpoints enable server-to-server communications and are not meant for the general public. And yet, GraphQL’s feature of introspection makes this possible without much difficulty. 

Assume the instance where someone sends a query against an internal endpoint only to gain access to admin credentials and thereby obtain Admin Privilege. 

Here is an example of a single endpoint which has the potential to allow attackers to access hidden API calls from the backend. 

Hidden API calls in GraphQL

 

There are several websites such as https://apis.guru/graphql-voyager/ that display the entire list of API calls available at the backend. This provides a better understanding of the its interface and also demonstrates ways to gather sensitive information from the server. 

Entire list of GraphQL API calls

We have covered a few of the misconfigurations here, but there could be many others. Also, it is vulnerable to all bugs that affect any other API.

 

Testing common misconfigurations in GraphQL

Here we’ll be exploring two ways to test these common misconfigurations, further exploited to gain access to sensitive data or information:

  • Burp Suite – Advance intercepting proxy tool
  • Altair GraphQL – GraphQL interface available as software, extension for OS and browser.

 

Testing GraphQL misconfigurations with Burp Suite

Burp Suite is a popular pentesting framework that works as a great proxy tool to intercept and visualize requests. Assuming that readers are already aware of how to configure it, we’ll be focusing on testing alone. 

  • This is what a normal HTTP request in GraphQL looks like:Normal HTTP request on GraphQL
  • Modify the POST query per your requirements and send it to the server. 
  • If it is misconfigured, it will fetch sensitive/ internal data. 
  • However, if you find it difficult to visualize or modify the query, you can use a Burp plugin called “GraphQL” to achieve the same results.

Burp plugin for GraphQL

 

But the major drawback of testing it in Burp Suite is the inadequate visualization of the entire schema documentation. This could result in several common misconfigurations being overlooked, unless we locate the proper documentation of API endpoints or calls implemented at the backend. Another issue related to using Burp is that we have to modify or debug the query manually which makes the process more complex. All these issues can be resolved with the help of the following method.

 

Debugging GraphQL with Altair GraphQL 

Altair helps with debugging GraphQL queries and server implementations. It rectifies the problem of modifying the queries manually and instead helps to focus on other aspects. 

Altair GraphQL is available as a software for Mac, Linux, and Windows OS and also as an extension for almost all browsers. It provides proper documentation of the entire schema that is available at the backend. All we need to do is configure the web application we are testing.

Three operations of GraphQL

 

All three operations of GraphQL can be seen in the documentation section as shown above. You can further explore these options to get other fields, API endpoints, etc.

Adding supported values

 

Altair is capable of solving one of the most challenging tasks in this process: Adding a query manually. It comes with the feature that enables automatic query generation. So, all we need to do is pass supported type values.

Add Query

 

  • Click on the ADD QUERY as shown above, to automatically add a query along with its arguments and fields. 
  • Now, provide the argument values to test for any bugs or misconfigurations.

Altair GraphQL

 

Altair makes bug hunting on any web application quite easy. You can test GraphQL queries and server implementations easily, as Altair performs the complex part of the process and lets you focus on the results.

 

Conclusion

In comparison with REST API, GraphQL offers developers improved standards of API development. And yet, it has its own security misconfigurations that can be exploited relatively easily. However, it is capable of bridging the gaps created by REST API. Alternatively, REST can help address the drawbacks of GraphQL as well. They need not be referred to as two incompatible technologies. Moreover, we believe these technologies can coexist with each other.

GraphQL 101: Here’s everything you need to know about GraphQL

 

API or an Application Program Interface is a family of protocols, commands, and functions that are used to build and integrate application software. In essence, API is the intermediary that enables two applications to connect. And for years, REST API was recognized as the standard protocol for web APIs. However, there is a visible trend that could potentially upend this inclination towards REST API. The State of Javascript 2018 report finds that, out of the developers who were surveyed in 2016, only 5% used GraphQL. Whereas in 2018, the numbers rapidly increased to a massive 20.4%. Although these numbers do not represent the preference of GraphQL over REST API, this clearly indicates the significant growth in the number of developers who opt for GraphQL in web applications. 

In a two-part series about GraphQL, we discuss the following topics:

  • Introduction to GraphQL 
  • GraphQL vs. REST
  • GraphQL’s declarative data fetching
  • GraphQL: Common misconfigurations that enable hackers
  • Testing common misconfigurations in GraphQL

In this part, we explore:

  • What is GraphQL?
  • How to identify a GraphQL instance?
  • How to configure the GraphQL server?
  • Root types of GraphQL schema
  • GraphQL vs. REST (focused on data fetching)
  • GraphQL: Smooth, declarative data fetching

 

Introduction to GraphQL

What is GraphQL?

It is an open source query language for APIs that helps to load data from a server to the client in a much simpler way. Unlike REST APIs, GraphQL APIs are arranged as types and fields and not as endpoints. This feature ensures that applications can request for only what can be obtained to provide clear responses. GraphQL API fetches the exact data requested; nothing less, nothing more.

It was developed by Facebook in 2012 and was later publicly released in 2015. Today, GraphQL is rapidly adopted by clients, big and small, from all over the world. Prominent websites and mobile apps such as Facebook, Twitter, GitHub, Pinterest, Airbnb, etc. use GraphQL.

REST API suffers from the lack of a robust API documentation making it difficult for developers to know the specific operations that the API supports and how to use them efficiently. But the GraphQL schema properly defines its operations, input values, and possible outcomes. When a client sends a query request, GraphQL’s resolver function fetches the result from the source.

GraphQL resolver

GraphQL allows frontend developers to retrieve data from the backend with unparalleled ease, which explains why it is generally described as Frontend Directed API technology. Evidently, it is more efficient, powerful, and flexible, and is a better alternative to REST API. 

 

How to identify a GraphQL instance?

  • A GraphQL HTTP request is typically sent to the following endpoints:
    • /graphql
    • /graphql/console
    • /graphiql
  • The GraphQL request looks similar to JSON but it’s different, as seen in the following request:

JSONWhile pentesting a web application, if you come across any of the above-mentioned attributes, then it most probably uses GraphQL.

 

How to configure the GraphQL server?

We can run the GraphQL API server on localhost with the use of Express, a web application framework for Node.js. 

  • For this, after you have installed “npm” proceed to install two additional dependencies which can be done using the following command:
npm install express express-graphql graphql --save
  • For more clarity of the concept, this is how we fetch “hello world” data from the GraphQL server using a query. 

 

var express = require('express');

var graphqlHTTP = require('express-graphql');


var { buildSchema } = require('graphql');

// Construct a schema, using GraphQL schema language

var schema = buildSchema(`

  type Query {

    hello: String

  }

`);

// The root provides a resolver function for each API endpoint

var root = {

  hello: () => {

    return 'Hello world!';

  },

};

var app = express();

app.use('/graphql', graphqlHTTP({

  schema: schema,

  rootValue: root,

  graphiql: true,

}));

app.listen(4000);

console.log('Running a GraphQL API server at http://localhost:4000/graphql');
  • Save the subsequent code as GraphQL_Server.js.
  • Now, run this GraphQL server with: 
node GraphQL_Server.js
  • If you don’t encounter an error, that means we have successfully configured our GraphQL server and we are good to proceed.Configuring GraphQL
  • Navigate to the endpoint http://locahost:4000/graphql in a web browser where you will come across the GraphQL interface. You can now enter your queries here. Entering a query in GraphQL
  • Once the query “hello” is issued, it fetches the following data from the server:

Hello World on GraphQL

Root types of GraphQL schema

GraphQL schema has three root types. Requests against GraphQL endpoint should start with any of these root types while communicating with the server:

  • Query: This type allows reading or fetching data from the backend server.GraphQL query
  • Mutation: This type is used to create, edit, or delete data. GraphQL Monitoring
  • Subscriptions: This root type enables real-time communication, to automatically receive real-time updates about particular events.

GraphQL Subscription

GraphQL is said to be client-driven, as it allows clients to add new fields and types to the GraphQL API and provide each field with functions. Clients can ultimately decide the exact response they require for queries. Contrary to how REST API operates, GraphQL permits clients to retrieve essential data alone, instead of the complete data.

 

GraphQL vs. REST

Both REST and GraphQL help developers design the functioning of APIs, and the process by which applications will be able to access data from it. They send data over HTTP. However, there are quite a few differences between them which prove that GraphQL is superior. 

A key differentiator is a method of fetching data from the backend server. While a typical REST API sends multiple requests to load data from multiple URLs, GraphQL has to send only a single request, to get the most accurate response, leaving out unwanted data behind. This is called declarative data fetching. Here’s an example to help you understand this better.

In REST API, multiple requests are sent at multiple endpoints to fetch the specific or particular data from the server. For instance, in order to fetch a user’s ID, his posts on a social media platform, and his followers on the same channel, we have to send multiple requests at the endpoint using the right path such as /user/<id>, /users/id/<posts>, and /users/id/<followers>  respectively, only to get multiple responses regarding the same.

REST API multiple endpoints

 

However, in the case of GraphQL, a single query, that includes all three requests, at a single endpoint will be enough to retrieve accurate responses to the corresponding requests. All we need to do is send a query through the interface, which gets interpreted against the entire schema, and returns the exact data that the client requested.

 

Smooth, declarative data fetching

In the instance of REST API mentioned above, we saw that 3 requests were made at 3 different endpoints to retrieve the corresponding response from the server. But in GraphQL, this process is relatively easier. A query that includes the exact data requirements like IDs, posts, and followers at a single endpoint would do the job. 

Let’s have a look at the query that is sent to the server to fetch a user’s ID, posts, and followers:

GraphQL endpoint

The above image shows how a query that includes data requirements is sent to the backend server, for which it’s response is retrieved at the client-side. 

The dissimilarities between REST and GraphQL is quite significant and can be understood while comparing their functioning. 

Difference between GraphQL and REST API

 

However, these differences do not necessarily mean that REST is not as efficient or flexible, after all it has been the standard API for several years now. However, GraphQL is gaining popularity because it addresses and bridges the shortcomings of REST API. 

In next week’s blog, we will explore the common GraphQL misconfigurations that enable hackers, and how you can test them.