# GraphQL

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

To identify exposed GraphQL instances, the inclusion of specific paths in directory brute force attacks is recommended. These paths are:

```txt
/graphql
/graphiql
/graphql.php
/graphql/console
/api
/api/graphql
/graphql/api
/graphql/graphql
```

Identifying open GraphQL instances allows for the examination of supported queries. This is crucial for understanding the data accessible through the endpoint. GraphQL's introspection system facilitates this by detailing the queries a schema supports. For more information on this, refer to the GraphQL documentation on introspection: [**GraphQL: A query language for APIs.**](https://graphql.org/learn/introspection/)

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

We can fetch field information by sending queries.

{% code overflow="wrap" lineNumbers="true" %}

```graphql
query {
	__typename
}
```

{% endcode %}

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

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

{% code overflow="wrap" lineNumbers="true" %}

```graphql
query {
	user {
		name
		friends {
			name
		}
	}
}
```

{% endcode %}

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

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

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

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

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

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

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

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

{% code overflow="wrap" lineNumbers="true" %}

```graphql
query {
	firstUser: user (id: "1") {
		...userFields
	}
	secondUser: user (id: "2") {
		...userFields
	}
	
	fragment userFields on User {
		name
		age
		friends {
			name
		}
	}
}
```

{% endcode %}

### 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.

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

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

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

#### 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`.

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

* **skip**

Skip this field if the argument is `true`.

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

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

We can modify fields with the `mutation` field.

{% code overflow="wrap" lineNumbers="true" %}

```graphql
mutation {
	__typename
}
```

{% endcode %}

To modify a field, execute like the following.

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

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

{% code overflow="wrap" lineNumbers="true" %}

```graphql
# 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 } }
```

{% endcode %}

## 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/security-risk/sql-injection-cheat-sheet/) for more payloads.

{% code overflow="wrap" lineNumbers="true" %}

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

{% endcode %}

## NoSQL Injection

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

***

## References

* <https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/GraphQL%20Injection>
* <https://graphql.org/learn/queries/>
* <https://escape.tech/blog/pentest101/>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pcastagnaro.gitbook.io/pentest-bug-bounty-resources/pentest-bounty-resources/web/injection/graphql.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
