O GraphQL oferece a flexibilidade de solicitar exatamente os recursos e atributos de que você precisa - nada mais, nada menos. Isso é diferente do REST, que muitas vezes busca dados demais ou de menos. Essa precisão torna o GraphQL altamente eficiente. Além disso, o GraphQL oferece maneiras padrão de lidar com a paginação, aumentando ainda mais sua flexibilidade. No entanto, usuários mal-intencionados podem explorar esses recursos do GraphQL, o que pode representar riscos significativos para a estabilidade do seu servidor.
Neste blog, exploraremos como a flexibilidade do GraphQL pode se voltar contra você. Estamos nos concentrando especificamente em uma vulnerabilidade destacada pelo OWASP API Security Top 10: consumo irrestrito de recursos. Também discutiremos as etapas práticas para proteger seus sistemas contra esse tipo de abuso.
Resposta do GraphQL à busca excessiva e à busca insuficiente
O GraphQL foi projetado em parte para resolver os problemas de busca excessiva que normalmente encontramos com o REST. Por exemplo, vamos considerar um banco de dados de comércio eletrônico padrão com usuários, produtos e pedidos. Imagine a necessidade de buscar o valor total em dólares de um pedido, com base no ID do pedido. Com o REST, essa solicitação GET para /orders/17 buscaria não apenas o valor em dólares, mas também o seguinte:
- dados do pedido
- informações de faturamento
- informações de remessa
- quantidades de produtos
- imposto
- status do pedido
- ... e mais
Isso é buscar demais.
Com o REST, você também encontra sub-busca quando precisa reunir dados associados de vários recursos. Imagine que você queira exibir um resumo, com a data e o status de um pedido, os nomes e as descrições de todos os produtos do pedido e o nome e o e-mail do usuário que fez o pedido. Para fazer isso, você precisaria enviar várias solicitações:
- GET /orders/17
- GET /produtos/1662527
- GET /produtos/9914188
- GET /produtos/3750021
- GET /produtos/7557109
- GET /products/6081142
- GET /users/3314
O GraphQL foi a resposta para essas deficiências do REST. Você pode consultar exatamente o que precisa, em todos os recursos associados. Para realizar o que foi mencionado acima, seu GraphQL pode ter a seguinte aparência:
query { |
É tão simples e flexível! No entanto, esse nível de flexibilidade também significa que um usuário mal-intencionado pode deliberadamente buscar dados em excesso.
Abusar da flexibilidade da consulta
A sintaxe de consulta do GraphQL permite que você execute várias consultas na mesma solicitação. Poderíamos usar a consulta acima e fazer algo assim:
query { |
Desta vez, solicitamos os mesmos dados da consulta anterior, só que os solicitamos duas vezes. Naturalmente, a resposta teria o dobro do tamanho da solicitação de consulta única. No entanto, e se repetíssemos a consulta 100 vezes em uma única solicitação?
query { |
Dessa forma, criamos uma consulta que produziria uma resposta 100 vezes maior do que a consulta original. Uma boa maneira de ilustrar esse ataque é com a seguinte imagem de cheeseburgers. Os pães de hambúrguer formam a única solicitação, mas, entre os pães, você pode ter centenas de hambúrgueres!
Se um usuário mal-intencionado abusar dessa flexibilidade de consulta, o consumo excessivo de recursos poderá sufocar o seu servidor.
Uso indevido de recursos de paginação
O GraphQL também tem algumas formas padrão de lidar com a paginação. Uma abordagem comum é a paginação baseada em deslocamento, na qual o chamador fornece o número de itens a serem buscados (limite) e o item com o qual começar (deslocamento).
Por exemplo, uma consulta para retornar informações de uma pesquisa de produto pode ser assim:
query { |
E se ajustássemos os parâmetros de paginação para executar essa consulta em vez disso?
query { |
Em um conjunto semelhante de exemplos que testei em um site de comércio eletrônico, comparei as respostas que recebi:
$ du response*.json |
Você poderia pensar que o arquivo grande teria aproximadamente 100 vezes o tamanho do arquivo pequeno, já que o limite foi definido como 800 em vez de 8. A pesquisa provavelmente não produziu 800 resultados no total (possivelmente apenas 16 a 20).
O abuso da paginação é outro exemplo de como alguém pode manipular os parâmetros de consulta do GraphQL para adicionar carga ao seu servidor. Ao explorar esse recurso, os invasores podem forçar seu servidor a lidar com solicitações muito maiores do que o pretendido, o que pode levar ao esgotamento de recursos e à negação de serviço (DoS).
OWASP API4:2023 Consumo irrestrito de recursos
O que estamos demonstrando se enquadra no Top 10 de segurança de API da OWASP, especificamente na API4:2023 Consumo irrestrito de recursos. Essa vulnerabilidade ocorre quando as APIs não limitam determinados tipos de interações ou solicitações, deixando o servidor vulnerável a ataques de DoS e outras interrupções operacionais.
Quando uma API permite consultas excessivas ou paginação sem limites, isso pode levar a um consumo de recursos em espiral. Isso, por sua vez, pode causar degradação do desempenho ou até mesmo falha total do servidor. Sem a implementação de limites adequados, esses ataques podem interromper o serviço. Você pode incorrer em altos custos operacionais, ver os clientes se afastarem e perder negócios.
Como se proteger
Para lidar com esses riscos, você precisa regular adequadamente as solicitações de API. Implemente controles que restrinjam a quantidade de dados que podem ser solicitados. Isso inclui a definição de limites para o tamanho e o número de consultas, bem como a implementação de limitação de taxa e outras medidas de proteção.
Aqui estão algumas sugestões práticas para se proteger:
- Limites de tamanho da carga útil da solicitação e da resposta: Ao definir limites para o tamanho dos dados que podem ser solicitados e retornados, você pode evitar que consultas muito grandes sobrecarreguem o servidor.
- Limites de paginação: Implemente um limite máximo para paginação, garantindo que um chamador não tente buscar mais registros do que o razoável.
- Firewall de aplicativos da Web (WAF): Um WAF pode ajudar a detectar e bloquear atividades mal-intencionadas, impedindo possíveis ataques à sua API GraphQL. Considere usar um WAF como o Haltdos do Linode Marketplace para adicionar essa camada extra de segurança.
- Ferramentas de segurança de API: As ferramentas que podem detectar e atenuar atividades mal-intencionadas são essenciais. Elas podem ajudar a identificar padrões incomuns que podem indicar um ataque, permitindo que você tome medidas antes que ele afete seu sistema.
Ao adotar essas etapas, você pode reduzir significativamente o risco de exploração do seu servidor GraphQL por meio do consumo excessivo de recursos. Garantir que as interações da API sejam reguladas adequadamente ajudará a manter a estabilidade e o desempenho do seu servidor.
Para obter mais informações sobre a criação com GraphQL, consulte GraphQL Apollo: Uma introdução com exemplos em nossa documentação.
Comentários