# GraphQL Pentesting

An open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.

### Common Directories <a href="#common-directories" id="common-directories"></a>

```shellscript
/graphql
/graphiql
/graphql.php
/graphql/console
```

### Basic Operations - Queries <a href="#basic-operations-queries" id="basic-operations-queries"></a>

We can fetch field information by sending queries.

```shellscript
query {
    __typename
}
```

#### Fields <a href="#fields" id="fields"></a>

To fetch a field object, send a query like the following.

```shellscript
query {
    user {
        name
        friends {
            name
        }
    }
}
```

#### Arguments <a href="#arguments" id="arguments"></a>

We can get the specific information by padding arguments (e.g. `id`) to fields.

```shellscript
query {
    user (id: "1") {
        name
    }
}
```

#### Aliases <a href="#aliases" id="aliases"></a>

We can set aliases each field to get multiple results in one request.

```shellscript
query {
    John: user (id: "1") {
        name
        age
    }
    Emma: user (id: "2") {
        name
        age
    }
}
```

#### Fragments <a href="#fragments" id="fragments"></a>

We can define arbitrary fragment that is be reusable when fetching each field.

```shellscript
query {
    firstUser: user (id: "1") {
        ...userFields
    }
    secondUser: user (id: "2") {
        ...userFields
    }

    fragment userFields on User {
        name
        age
        friends {
            name
        }
    }
}
```

#### Operation Names <a href="#operation-names" id="operation-names"></a>

We can define an operation name to make an operation less ambiguous. By setting a name, it makes it easier to understand at a glance what kind of operation.

```shellscript
query UserNameAndFriends {
    user {
        name
        friends {
            name
        }
    }
}
```

#### Variables <a href="#variables" id="variables"></a>

```shellscript
query UsrNameAndFriends($userId: ID) {
    user (id: $userId) {
        name
        friends {
            name
        }
    }
}
```

#### Directives <a href="#directives" id="directives"></a>

We can filter by passing a directive in fields.

* **include**

Only include this field if the argument is `true`.

```shellscript
query UserNameAndFriends($userId: ID, $withFriends: Boolean!) {
    user(id: $userId) {
        name
        friends @include(if: $withFriends) {
            name
        }
    }
}
```

* **skip**

Skip this field if the argument is `true`.

```shellscript
query UserNameAndFriends($userId: ID, $withFriends: Boolean!) {
    user(id: $userId) {
        name
        friends @skip(if: $withFriends) {
            name
        }
    }
}
```

### Basic Operations - Mutations <a href="#basic-operations-mutations" id="basic-operations-mutations"></a>

We can modify fields with the `mutation` field.

```shellscript
mutation {
    __typename
}
```

To modify a field, execute like the following.

```shellscript
mutation CreateCommentForPost($postId: ID!, $comment: Comment!) {
    createComment(id: $postId, comment: $comment) {
        comment
    }
}
```

### Enumeration <a href="#enumeration" id="enumeration"></a>

```shellscript
# List fields
query { __schema { types { name } } }
query { __schema { types { fields { name } } } }
query { __schema { types { fields { name description } } } }
query { __schema { types { name fields { name } } } }
query { __schema { types { name fields { name args { name description type { name kind ofType { name kind } } } } } } }

# Dump database schema
fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason }  possibleTypes { ...TypeRef }} fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } }} query IntrospectionQuery { __schema { queryType { name } mutationType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } }

# Dump specific field
query { getUsers { username, password } }
```

### SQL Injection <a href="#sql-injection" id="sql-injection"></a>

We might be able to inject SQL somewhere e.g. arguments. Please refer to [SQL Injection Cheat Sheet](https://exploit-notes.hdks.org/exploit/web/sql-injection-cheat-sheet/) for more payloads.

```shellscript
{
    user (id: "1' UNION SELECT null,null-- -") {
        name
        password
    }
}
```

### NoSQL Injection <a href="#nosql-injection" id="nosql-injection"></a>

We might be able to inject NoSQL somewhere e.g. arguments. Please refer to [NoSQL Injection](https://exploit-notes.hdks.org/exploit/web/nosql-injection/) for more payloads.

### References <a href="#references" id="references"></a>

* [GraphQL Docs](https://graphql.org/learn/queries/)
* [PayloadAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection)
* [escape](https://escape.tech/blog/pentest101/)
