- Seguridad y Privacidad
- Base de conocimiento
- Object Limit Overriding in GraphQL
Anulación del límite de objetos en GraphQL
Descripción
La anulación de límite de objetos (Object Limit Overriding) en GraphQL se refiere a una vulnerabilidad donde un atacante puede manipular los argumentos de la consulta para superar los límites previstos de una API. Esto a menudo implica pasar valores extremadamente grandes a los parámetros de paginación o límite, lo que puede provocar ataques de denegación de servicio (DoS) o un consumo excesivo de recursos.
Riesgos potenciales:
Denegación de servicio (DoS): Al solicitar un número excesivo de objetos, los atacantes pueden abrumar el servidor, causando degradación del rendimiento o interrupciones.
Agotamiento de recursos: Las consultas que solicitan una gran cantidad de objetos pueden sobrecargar la memoria y las capacidades de procesamiento del servidor.
Exposición de datos: En algunos casos, eludir los límites podría llevar al acceso no autorizado a grandes cantidades de datos.
Aumento de costos: Para los servicios basados en la nube, el procesamiento de consultas con límites extremadamente altos puede resultar en costos inesperados debido al alto uso de recursos.
Ejemplo de consulta vulnerable:
query {
users(first: 1000000) {
id
name
email
}
}
Recomendación
Para mitigar el riesgo de la anulación del límite de objetos en GraphQL, implemente las siguientes medidas:
Análisis de la complejidad de la consulta: Utilice herramientas o bibliotecas para analizar y limitar la complejidad de las consultas entrantes. Bibliotecas como graphql-query-complexity pueden ayudar.
Limitación de velocidad (Rate Limiting): Implemente la limitación de velocidad para restringir el número de consultas que puede enviar un solo usuario o dirección IP dentro de un período de tiempo determinado.
Paginación y límites: Aplique límites a la cantidad de datos devueltos en una sola consulta. Asegúrese de que se utilice la paginación para controlar el volumen de datos.
Example Implementation:
const { ApolloServer, gql } = require('apollo-server');
const { getComplexity, simpleEstimator, fieldExtensionsEstimator } = require('graphql-query-complexity');
const { GraphQLObjectType, GraphQLInt, GraphQLString, GraphQLSchema } = require('graphql');
// Define your GraphQL schema
const typeDefs = gql`
type Query {
hello: String
user(id: ID!): User
}
type User {
id: ID!
name: String
age: Int
}
`;
// Define your resolvers
const resolvers = {
Query: {
hello: () => 'Hello world!',
user: (_, { id }) => ({
id,
name: 'John Doe',
age: 30,
}),
},
};
// Create an Apollo Server instance with query complexity analysis
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [
{
// This plugin computes the complexity of incoming queries
requestDidStart: () => ({
didResolveOperation({ request, document }) {
const complexity = getComplexity({
schema: server.schema,
query: document,
variables: request.variables,
estimators: [
fieldExtensionsEstimator(),
simpleEstimator({ defaultComplexity: 1 }),
],
});
// Define a maximum complexity limit
const maxComplexity = 100;
// Check if the query complexity exceeds the maximum allowed
if (complexity > maxComplexity) {
throw new Error(`Query is too complex: ${complexity}. Maximum allowed complexity: ${maxComplexity}`);
}
},
}),
},
],
});
// Start the server
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
from graphql import parse, execute, validate, GraphQLError
from graphql.language.visitor import visit, Visitor
class ComplexityVisitor(Visitor):
def __init__(self):
self.complexity = 0
self.max_complexity = 100
def enter_field(self, node, key, parent, path, ancestors):
complexity = 1 # Base complexity for each field
self.complexity += complexity
if self.complexity > self.max_complexity:
raise GraphQLError(f"Query complexity exceeds maximum allowed complexity of {self.max_complexity}")
def complexity_middleware(schema, query):
document = parse(query)
visitor = ComplexityVisitor()
visit(document, visitor)
return visitor.complexity
def execute_with_complexity_check(schema, query, variables=None):
complexity = complexity_middleware(schema, query)
if complexity > 100:
raise GraphQLError(f"Query complexity exceeds maximum allowed complexity of 100")
result = execute(schema, parse(query), variable_values=variables)
return result
By using these recommendations and configurations, you can better protect your GraphQL APIs from the risks associated with object limit overriding.
Detecte este problema con Ostorlab
Ostorlab busca este problema en aplicaciones web, API y redes.
Crear una cuentaEnlaces
- GraphQL Vulnerabilities and Common Attacks: What You Need to Know
- OWASP GraphQL Security Cheat Sheet
Estándares
- CWE_TOP_25:
- CWE_20
- CWE_400
- PCI_STANDARDS:
- REQ_6_1
- REQ_6_2
- REQ_6_4
- REQ_11_3
- OWASP_MASVS_L2:
- MSTG_PLATFORM_2
- OWASP_ASVS_L3:
- V13_4_1
- SOC2_CONTROLS:
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- CC_9_1
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- OWASP_TOP_10:
- A03_2021