Exploiting SQL Injection in Graphql | DVGA |

Medusa
InfoSec Write-ups
Published in
5 min readMar 2, 2023

--

This article covers exploiting SQL Injection manually in a Graphql Application.

Graphql Introduction

Graphql is a query language for APIs used to interact with the back end. It works as an intermediate between the client and the backend. It is like the REST API but unlike the REST API that uses a number of different endpoints to perform CRUD (Create, Read, Update, Delete), graphql only uses one endpoint and only the query changes.

SQL Injection

SQL Injection is a web security vulnerability that allows an attacker to manipulate the data that is interacting with the database by sending malicious code. So instead of data, a malicious query is sent to the database and due to the improper handling of data, critical information is leaked about the backend which can lead to a whole database takeover.

Steps to exploit SQL Injection:-

  1. Find a parameter or an endpoint that takes user input to interact with the database.
  2. Try injecting different SQL payloads and check the response. Does it throw errors or does it take too much time to respond? (Blind SQL injection).

Exploiting SQL Injection in a Graphql application is very similar to a non-API application. For demonstration purposes, we will use Damn Vulnerable Graphql Application (DVGA).

SS 1

This is how the application look like, it has this page where users can see pastes that are posted by other users and is “public”.

SS 2

In the network tab, we can see there is a graphql endpoint fetching public pastes through a query.

SS 3

In the response, we can see a number of objects with fields like id, title, content,ipAddr, etc. These are the data related to each paste in the application.

Graphql Endpoint Enumeration

To interact with the graphql, the first step should be to find graphql endpoint. This can be achieved by using fuzzing tools. I used kiterunner with wordlist graphql.txt from seclists to find the endpoint and the result was /graphiql.

SS 4

From the screenshot above, we can see that graphql console is exposed but we still can’t interact with it.

SS 5

In the cookies, there’s a value graphql:disable, by changing it to enable we can interact with the graphql console.

In the documentation explorer, there are a number of queries along with their arguments. We are going to test on pastes object.

SS 6

This is a query for pastes object which can take three arguments: public, filter, and limit. If the public is set to true, it will fetch all public pastes but if set to false it will fetch private pastes. The filter argument takes a string as a value and fetches pastes that have the provided value in it. In this case, I’ve copied a title from the public pastes and pasted it in the filter argument. (Check the first screenshot).

In the response, we can see two pastes that have the keyword in their title that we provided in the filter. So this argument is interacting with the database to fetch something according to the user input.

If you want to understand how queries and mutation work, check this out!

Exploitation

To test for SQL Injection, we are going to use a single quote and check the response.

SS 7

Interesting! An error occurred and it says sqlite3.operational error with some other info about the SQL syntax.

SS 8

This SQL payload leads to a true condition because 1=1 is true and that’s why it fetched all the public pastes. It confirms it is vulnerable to SQL Injection.

SQL Injection UNION Attack

Finding the number of columns

The next step is to find the number of columns in the current table to perform a UNION attack. For that purpose, we can use the ORDER BY clause by incrementing the number of columns in the query until an error occurs.

Payload: ' ORDER BY 1,2,3,4,5,6,7,8--
SS 9

By incrementing it to 9, an error occurred which means there are a total of eight columns.

Finding column that holds “String”

We want to extract username and password from the SQL database, and that is usually in string form, so we need to find out which column can hold string data type.

Payload: ' UNION SELECT 'a',2,3,4,5,6,7,8--
' UNION SELECT 1,'a',3,4,5,6,7,8--
and so on..
SS 10

If the input is reflected in the response(in this case ‘a’), means that the table can hold string data type. From the testing, it is found that the first and second columns can hold string data types.

SS 11
Payload: ' UNION SELECT sql,2,3,4,5,6,7,8 FROM sqlite_schema--

The above SQL payload will extract the table structure from the backend.

Find SQLite injection cheat sheet here.

In the last entry, we can see a users table that has columns username and password.

SS 12
Payload: ' UNION SELECT username,password,3,4,5,6,7,8 FROM users--

From the last payload, we were able to extract the username and password of the admin. As we can see how critical it can be to able to extract sensitive information through an exposed graphql console just by looking at the schema.

If you would like to watch a practical video, check this out:

Thank you for Reading!

Twitter: medusa_0xf

--

--