GraphQL Güvenliği: Derinlik Limitleme ve Query Whitelisting
Merhaba değerli okuyucular! Bugün, modern web uygulamalarında giderek daha popüler hale gelen GraphQL'in güvenlik yönlerini, özellikle de derinlik limitleme ve query whitelisting tekniklerini inceleyeceğiz. Bu güvenlik önlemlerinin nasıl uygulanacağını ve neden önemli olduklarını detaylıca ele alacağız. Hazırsanız, GraphQL güvenliğinin derinliklerine dalalım!
GraphQL Güvenlik Riskleri
GraphQL'in esnek yapısı, bazı güvenlik risklerini de beraberinde getirir:
- Karmaşık ve maliyetli sorgular
- Derinlik saldırıları
- Hassas veri sızıntıları
- DoS (Denial of Service) saldırıları
Derinlik Limitleme
Derinlik limitleme, bir GraphQL sorgusunun ne kadar derinleşebileceğini sınırlar. Bu, potansiyel olarak maliyetli ve tehlikeli derinlik saldırılarını önler.
Derinlik Limitleme Örneği (Node.js ve graphql-depth-limit):
const { ApolloServer } = require('apollo-server'); const depthLimit = require('graphql-depth-limit'); const server = new ApolloServer({ typeDefs, resolvers, validationRules: [depthLimit(5)] // Maksimum 5 seviye derinlik }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Özel Derinlik Limitleme Fonksiyonu:
function createDepthLimitRule(maxDepth) { return function (validationContext) { return { Field(node, key, parent, path, ancestors) { if (ancestors.length > maxDepth) { validationContext.reportError( new GraphQLError( `Query exceeds maximum depth of ${maxDepth}`, [node] ) ); } } }; }; } // Kullanım const server = new ApolloServer({ typeDefs, resolvers, validationRules: [createDepthLimitRule(5)] });
Query Whitelisting
Query whitelisting, yalnızca önceden onaylanmış sorguların çalıştırılmasına izin vererek, potansiyel kötü niyetli sorguları engeller.
Query Whitelisting Örneği (Apollo Server ve Persisted Queries):
const { ApolloServer } = require('apollo-server'); const { createHash } = require('crypto'); const allowedQueries = new Map(); // Önceden onaylanmış sorguları ekleyin allowedQueries.set( createHash('sha256').update('query { hello }').digest('hex'), 'query { hello }' ); const server = new ApolloServer({ typeDefs, resolvers, persistedQueries: { cache: allowedQueries } }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Özel Query Whitelisting Implementasyonu:
const allowedQueries = new Set([ 'query { user(id: $id) { name email } }', 'query { posts { title author { name } } }' ]); function validateQuery(query) { // Sorguyu normalize et (boşlukları ve yeni satırları kaldır) const normalizedQuery = query.replace(/s+/g, ' ').trim(); return allowedQueries.has(normalizedQuery); } const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const query = req.body.query; if (!validateQuery(query)) { throw new Error('Bu sorguya izin verilmiyor'); } return {}; } });
Ek Güvenlik Önlemleri
1. Query Complexity Analysis
Sorgu karmaşıklığını analiz ederek, aşırı karmaşık sorguları engelleyin.
const { getComplexity, simpleEstimator } = require('graphql-query-complexity'); const server = new ApolloServer({ typeDefs, resolvers, validationRules: [ (context) => { return { Field(node) { const complexity = getComplexity({ schema: context.getSchema(), query: context.getDocument(), variables: context.getVariableValues(), estimators: [simpleEstimator({ defaultComplexity: 1 })] }); if (complexity > 100) { throw new Error('Sorgu çok karmaşık'); } } }; } ] });
2. Rate Limiting
Belirli bir zaman diliminde yapılabilecek sorgu sayısını sınırlayın.
const { createRateLimitRule } = require('graphql-rate-limit'); const rateLimitRule = createRateLimitRule({ identifyContext: (context) => context.id, max: 100, // maksimum istek sayısı window: '10s' // 10 saniyelik pencere }); const server = new ApolloServer({ typeDefs, resolvers, validationRules: [rateLimitRule] });
3. Input Sanitization
Kullanıcı girdilerini temizleyerek, potansiyel XSS ve injection saldırılarını önleyin.
const sanitizeHtml = require('sanitize-html'); const resolvers = { Mutation: { createPost: (_, { title, content }) => { const sanitizedTitle = sanitizeHtml(title); const sanitizedContent = sanitizeHtml(content); // Sanitize edilmiş verileri kullanarak post oluştur } } };
GraphQL Güvenlik Kontrol Listesi
GraphQL uygulamanızın güvenliğini sağlamak için bu kontrol listesini kullanabilirsiniz:
class GraphQLSecurityChecker { constructor() { this.checks = { depthLimiting: false, queryWhitelisting: false, complexityAnalysis: false, rateLimiting: false, inputSanitization: false }; } implementDepthLimiting() { // Derinlik limitleme implementasyonu this.checks.depthLimiting = true; } implementQueryWhitelisting() { // Query whitelisting implementasyonu this.checks.queryWhitelisting = true; } implementComplexityAnalysis() { // Karmaşıklık analizi implementasyonu this.checks.complexityAnalysis = true; } implementRateLimiting() { // Rate limiting implementasyonu this.checks.rateLimiting = true; } implementInputSanitization() { // Girdi temizleme implementasyonu this.checks.inputSanitization = true; } isSecure() { return Object.values(this.checks).every(check => check === true); } printSecurityStatus() { console.log("GraphQL Security Status:"); for (const [check, status] of Object.entries(this.checks)) { console.log(`${check}: ${status ? 'Implemented' : 'Not Implemented'}`); } console.log(`Overall Security: ${this.isSecure() ? 'Secure' : 'Not Secure'}`); } } // Kullanım örneği const securityChecker = new GraphQLSecurityChecker(); securityChecker.implementDepthLimiting(); securityChecker.implementQueryWhitelisting(); securityChecker.implementComplexityAnalysis(); securityChecker.implementRateLimiting(); securityChecker.implementInputSanitization(); securityChecker.printSecurityStatus();
GraphQL, güçlü ve esnek bir API teknolojisi olmasına rağmen, bu esneklik beraberinde güvenlik riskleri de getirebilir. Derinlik limitleme ve query whitelisting gibi teknikler, bu riskleri önemli ölçüde azaltır ve uygulamanızın güvenliğini artırır.
Ancak unutmayın ki, güvenlik sürekli bir süreçtir. Bu teknikleri uygulamanın yanı sıra, düzenli güvenlik denetimleri yapmak, güncel kalmak ve yeni ortaya çıkan tehditlere karşı hazırlıklı olmak önemlidir.
Siz GraphQL güvenliği için hangi önlemleri alıyorsunuz? Karşılaştığınız zorluklar veya paylaşmak istediğiniz ek öneriler var mı? Yorumlarınızı bekliyorum!
Güvenli kodlamalar ve güvenli GraphQL sorguları dilerim!