graphql - not - makeexecutableschema
¿Cómo se evita el ataque anidado en el servidor GraphQL/Apollo? (4)
Al momento de escribir, no hay una función incorporada en GraphQL-JS o Apollo Server para manejar esta preocupación, pero es algo que definitivamente debería tener una solución simple a medida que GraphQL se vuelve más popular. Esta inquietud puede abordarse con varios enfoques en varios niveles de la pila, y también debe combinarse siempre con la limitación de velocidad, para que las personas no puedan enviar demasiadas consultas a su servidor (esto también es un problema potencial con REST).
Solo enumeraré todos los diferentes métodos en los que puedo pensar e intentaré mantener esta respuesta actualizada a medida que estas soluciones se implementan en varios servidores GraphQL. Algunos de ellos son bastante simples, y algunos son más complejos.
- Validación de consultas : en cada servidor GraphQL, el primer paso para ejecutar una consulta es la validación . Aquí es donde el servidor intenta determinar si hay errores graves en la consulta, por lo que podemos evitar el uso de recursos reales del servidor si podemos encontrarlo. Hay algún error de sintaxis o argumento no válido por adelantado. GraphQL-JS viene con una selección de reglas predeterminadas que siguen un formato bastante similar a ESLint. Al igual que existe una regla para detectar ciclos infinitos en fragmentos , se podría escribir una regla de validación para detectar consultas con demasiado anidado y rechazarlas en la etapa de validación.
- Tiempo de espera de la consulta : si no es posible detectar que una consulta consumirá demasiada cantidad de recursos de manera estática (¡tal vez incluso las consultas superficiales pueden ser muy costosas!), Simplemente podemos agregar un tiempo de espera a la ejecución de la consulta. Esto tiene algunos beneficios: (1) es un límite difícil que no es demasiado difícil de razonar, y (2) esto también ayudará con situaciones en las que uno de los backends toma demasiado tiempo para responder. En muchos casos, un usuario de su aplicación preferiría un campo faltante en lugar de esperar más de 10 segundos para obtener una respuesta.
- Lista blanca de consultas : este es probablemente el método más complicado, pero puede compilar una lista de consultas permitidas con anticipación y verificar las consultas entrantes con esa lista. Si sus consultas son totalmente estáticas (no hace ninguna generación dinámica de consultas en el cliente con algo como Relay), este es el enfoque más confiable. Puede usar una herramienta automatizada para extraer cadenas de consulta de sus aplicaciones cuando se implementan, de modo que en el desarrollo escriba las consultas que desee pero en la producción solo se dejen pasar las que desea. Otro beneficio de este enfoque es que puede omitir la validación de consultas por completo, ya que sabe que todas las consultas posibles ya son válidas. Para obtener más beneficios de las consultas estáticas y las listas blancas, lea esta publicación: https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a
- Limitación de costos de consultas : (agregado en una edición) Al igual que los tiempos de espera de consultas, puede asignar un costo a diferentes operaciones durante la ejecución de la consulta, por ejemplo, una consulta de base de datos, y limitar el costo total que el cliente puede usar por consulta. Esto se puede combinar con la limitación del paralelismo máximo de una sola consulta, para que pueda evitar que el cliente envíe algo que inicie miles de solicitudes paralelas a su servidor.
(1) y (2) en particular son probablemente algo que todo servidor GraphQL debería tener por defecto, especialmente porque muchos desarrolladores nuevos pueden no estar conscientes de estas preocupaciones. (3) solo funcionará para ciertos tipos de aplicaciones, pero podría ser una buena opción cuando existen requisitos de seguridad o rendimiento muy estrictos.
¿Cómo evitar un ataque anidado contra un servidor Apollo con una consulta como:
{
authors {
firstName
posts {
title
author {
firstName
posts{
title
author {
firstName
posts {
title
[n author]
[n post]
}
}
}
}
}
}
}
En otras palabras, ¿cómo puede limitar el número de recursiones que se envían en una consulta? Esto podría ser una vulnerabilidad potencial del servidor.
Para complementar el punto (4) en la respuesta de stubailo, aquí hay algunas implementaciones de Node.js que imponen límites de costo y profundidad en los documentos GraphQL entrantes.
Estas son reglas personalizadas que complementan la fase de validación.
Para la limitación de costos de consultas, puede utilizar el graphql-cost-analysis
Esta es una regla de validación que analiza la consulta antes de ejecutarla. En su servidor GraphQL, solo tiene que asignar una configuración de costo para cada campo de su Mapa de tipos de esquema que desee.
Una variación en la lista blanca de consultas es la firma de consultas .
Durante el proceso de compilación, cada consulta se firma criptográficamente mediante un secreto que se comparte con el servidor pero no se incluye con el cliente. Luego, en tiempo de ejecución, el servidor puede validar que una consulta es genuina.
La ventaja sobre la lista blanca es que escribir consultas en el cliente no requiere ningún cambio en el servidor. Esto es especialmente valioso si varios clientes acceden al mismo servidor (por ejemplo, aplicaciones web, de escritorio y móviles).