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, os utilizadores maliciosos podem explorar estas funcionalidades do GraphQL, o que pode representar riscos significativos para a estabilidade do seu servidor.
Neste blogue, vamos explorar como a flexibilidade do GraphQL pode ser virada contra si. Estamos nos concentrando especificamente em uma vulnerabilidade destacada pelo Top 10 de segurança de API da OWASP: consumo irrestrito de recursos. Também discutiremos etapas práticas para proteger seus sistemas contra esse tipo de abuso.
A resposta do GraphQL para over-fetching e under-fetching
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 dado no ID do pedido. Com REST, esse pedido GET para /orders/17 iria buscar não apenas o valor em dólares, mas também o seguinte:
- dados da encomenda
- informações de faturação
- informações de envio
- quantidades de produtos
- fiscal
- estado da encomenda
- ... e mais
Isso é um exagero.
Com o REST, também se depara com a sub-busca, quando é necessário reunir dados associados de vários recursos. Imagine que pretende apresentar um resumo, com a data e o estado de uma encomenda, os nomes e as descrições de todos os produtos da encomenda e o nome e o e-mail do utilizador que efectuou a encomenda. Para o fazer, teria de enviar vários pedidos:
- GET /encomendas/17
- GET /produtos/1662527
- GET /produtos/9914188
- GET /produtos/3750021
- GET /produtos/7557109
- GET /produtos/6081142
- GET /usuários/3314
O GraphQL foi a resposta para essas deficiências do REST. É possível consultar exatamente o que você precisa, em recursos associados. Para realizar o que foi dito acima, seu GraphQL pode ter a seguinte aparência:
query { |
É tão simples e flexível! No entanto, este nível de flexibilidade também significa que um utilizador malicioso pode deliberadamente obter dados em excesso.
Abusar da flexibilidade das consultas
A sintaxe de consulta do GraphQL permite que você execute várias consultas na mesma solicitação. Poderíamos pegar a consulta acima e fazer algo assim:
query { |
Desta vez, solicitámos os mesmos dados que a consulta anterior, exceto que os solicitámos 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 num único pedido?
query { |
Sem mais nem menos, criámos uma consulta que produziria uma resposta 100 vezes maior do que a nossa consulta original. Uma boa maneira de ilustrar esse ataque é com a seguinte imagem de cheeseburgers. Os pães de hambúrguer formam o único pedido; mas entre os pães, pode haver centenas de hambúrgueres!
Se um utilizador malicioso abusar desta flexibilidade de consulta, o consumo excessivo de recursos pode sufocar o seu servidor.
Abusar das funcionalidades 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 devolver informações de uma pesquisa de produto pode ter o seguinte aspeto:
query { |
E se ajustássemos os parâmetros de paginação para executar esta consulta?
query { |
Num conjunto semelhante de exemplos que testei num sítio de comércio eletrónico, comparei as respostas que recebi:
$ du response*.json |
Poder-se-ia pensar que o ficheiro grande teria cerca de 100 vezes o tamanho do ficheiro pequeno, uma vez que o limite foi definido para 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 GraphQL para adicionar carga ao seu servidor. Ao explorar esta funcionalidade, os atacantes podem forçar o seu servidor a tratar pedidos muito maiores do que o pretendido, levando potencialmente ao esgotamento de recursos e à negação de serviço (DoS).
OWASP API4:2023 Consumo de recursos sem restrições
O que temos estado a demonstrar enquadra-se no Top 10 de segurança de API da OWASP, especificamente API4:2023 Unrestricted Resource Consumption. Esta vulnerabilidade ocorre quando as API não limitam determinados tipos de interações ou pedidos, deixando o servidor vulnerável a ataques DoS e outras perturbações operacionais.
Quando uma API permite uma consulta excessiva ou paginação sem limites, pode levar a um consumo de recursos em espiral. Isto, por sua vez, pode causar uma degradação do desempenho ou mesmo uma falha completa do servidor. Sem limites adequados, esses ataques podem interromper o serviço. Poderá incorrer em custos operacionais elevados, ver os clientes afastarem-se e perder negócio.
Como se proteger
Para lidar com estes riscos, é necessário regular corretamente os pedidos de API. Implemente controlos que restrinjam a quantidade de dados que podem ser solicitados. Isto inclui a definição de limites para o tamanho e o número de consultas, bem como a implementação de limitação de taxas e outras medidas de proteção.
Eis algumas sugestões práticas para se proteger:
- Limites de tamanho de carga útil de solicitação e resposta: Ao definir limites para o tamanho dos dados que podem ser solicitados e devolvidos, pode evitar que consultas demasiado grandes sobrecarreguem o seu servidor.
- Limites de paginação: Implementar um limite máximo para a paginação, garantindo que o chamador não tenta obter mais registos do que o razoável.
- Firewall de aplicativo Web (WAF): Um WAF pode ajudar a detetar e bloquear atividades mal-intencionadas, frustrando 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 da API: As ferramentas que podem detetar e mitigar actividades maliciosas são essenciais. Podem ajudar a identificar padrões invulgares que podem indicar um ataque, permitindo-lhe tomar medidas antes que este afecte o seu sistema.
Ao seguir essas etapas, é possível reduzir significativamente o risco de exploração do servidor GraphQL por meio do consumo excessivo de recursos. Garantir que suas interações de 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 o GraphQL, consulte GraphQL Apollo: Uma introdução com exemplos em nossos documentos.
Comentários