GraphQL Security
GraphQL oferece flexibilidade poderosa mas introduz vetores de ataque únicos: query complexity attacks, introspection abuse, authorization bypass e information disclosure.
Vulnerabilidades Comuns em GraphQL
1. Query Depth / Complexity Attacks
Queries deeply nested podem causar DoS consumindo recursos excessivos:
query MaliciousQuery {
user(id: "1") {
posts {
comments {
author {
posts {
comments {
author {
posts {
# ... infinitamente nested
}
}
}
}
}
}
}
}
}
2. Introspection Abuse
Introspection habilitado em produção revela schema completo, facilitando reconnaissance:
query IntrospectionQuery {
__schema {
types {
name
fields {
name
type {
name
}
}
}
}
}
3. Broken Authorization
Autorização deve ocorrer em resolvers, não apenas em queries top-level. IDOR comum quando authorization não é checked em nested fields.
4. Injection Attacks
GraphQL não imune a SQLi, NoSQLi se inputs não são sanitizados nos resolvers.
Proteções Essenciais
Query Depth Limiting
// Apollo Server example
import depthLimit from 'graphql-depth-limit';
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [depthLimit(5)] // Max depth 5
});
Query Complexity Analysis
import { createComplexityLimitRule } from 'graphql-validation-complexity';
const server = new ApolloServer({
validationRules: [
createComplexityLimitRule(1000, {
scalarCost: 1,
objectCost: 5,
listFactor: 10
})
]
});
Rate Limiting
- Query-based: Limitar queries por minuto por usuário
- Complexity-based: Budget de complexity points
- Cost analysis: Atribuir custo a cada field
Autorização em GraphQL
Field-Level Authorization
const resolvers = {
Query: {
user: async (parent, { id }, context) => {
// Autorização em query level
if (!context.user) {
throw new AuthenticationError('Not authenticated');
}
return getUserById(id);
}
},
User: {
email: (user, args, context) => {
// Autorização em field level
if (context.user.id !== user.id && !context.user.isAdmin) {
return null; // Ocultar email de outros usuários
}
return user.email;
},
ssn: (user, args, context) => {
// Field extremamente sensível
if (!context.user.isAdmin) {
throw new ForbiddenError('Admin only');
}
return user.ssn;
}
}
};
Directive-Based Authorization
type User @auth(requires: AUTHENTICATED) {
id: ID!
username: String!
email: String! @auth(requires: OWNER_OR_ADMIN)
ssn: String! @auth(requires: ADMIN)
}
Proteção de Introspection
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
// Ou controlar por role
plugins: [{
requestDidStart() {
return {
didResolveOperation({ request, context }) {
if (request.operationName === 'IntrospectionQuery'
&& !context.user?.isAdmin) {
throw new ForbiddenError('Introspection disabled');
}
}
}
}
}]
});
Input Validation
- Schema validation: GraphQL valida types automaticamente
- Custom scalars: Email, URL, DateTime com validation
- Input sanitization: Sanitizar inputs antes de usar em resolvers
- Parameterized queries: Usar prepared statements em database
Batching e DataLoader
Prevenir N+1 problem que pode ser explorado para DoS:
import DataLoader from 'dataloader';
const userLoader = new DataLoader(async (userIds) => {
const users = await getUsersByIds(userIds);
return userIds.map(id => users.find(u => u.id === id));
});
const resolvers = {
Post: {
author: (post, args, { userLoader }) => {
return userLoader.load(post.authorId); // Batched!
}
}
};
Monitoring e Logging
- Query logging: Log todas queries com metadata (user, IP, time)
- Error tracking: Sentry, Datadog para exceptions
- Performance monitoring: Apollo Studio, GraphQL Hive
- Anomaly detection: Alertar em queries suspeitas (muito complexas, etc.)
Ferramentas de Segurança
- GraphQL Armor: Security middleware suite
- graphql-shield: Permissions layer com rules
- InQL: Burp Suite extension para GraphQL pentest
- BatchQL: Security testing tool para GraphQL
- graphql-cop: Security auditing tool
OWASP GraphQL Top 10
- Broken Object Level Authorization
- Broken Authentication
- Excessive Data Exposure
- Resource Exhaustion
- Broken Function Level Authorization
- Mass Assignment
- Security Misconfiguration
- Injection
- Improper Assets Management
- Insufficient Logging & Monitoring
Práticas de Desenvolvimento Seguro
- Implementar autorização em TODOS os resolvers
- Desabilitar introspection em produção
- Limitar query depth e complexity
- Rate limiting agressivo
- Usar DataLoader para prevenir N+1
- Sanitizar inputs antes de processing
- Implementar comprehensive logging
- Regular security audits e pentests
Recomendações Finais
GraphQL exige mudança de mindset de segurança comparado a REST. Flexibilidade do client requer defesas robustas no server. Implemente depth limiting, complexity analysis e field-level authorization desde o início. Use ferramentas de monitoring para detectar abuse patterns. Teste regularmente com ferramentas especializadas como InQL e BatchQL.
