GraphQL ve REST API Güvenlik Karşılaştırması
API güvenliği denince çoğu sysadmin aklına hemen rate limiting ve API key yönetimi gelir. Oysa mesele bundan çok daha derin. Özellikle son yıllarda GraphQL’in yükselişiyle birlikte “hangi API mimarisini tercih etmeli ve nasıl güvence altına almalıyım?” sorusu gerçek bir baş ağrısına dönüştü. REST API’lerin yıllarca oluşturulan güvenlik pratiklerinin yanına GraphQL’in esnek ama tehlikeli olabilen yapısı eklenince, ortada ciddi bir karşılaştırma ihtiyacı doğdu.
REST API Güvenliğinin Temelleri
REST, kaynak odaklı yapısıyla tahmin edilebilir bir yüzey alanı sunar. Her endpoint belirli bir kaynağa karşılık gelir, HTTP metodları anlambilimsel olarak net bir şekilde ayrışır. Bu tahmin edilebilirlik güvenlik açısından hem bir avantaj hem de bir dezavantajdır.
Avantajı şu: Bir WAF (Web Application Firewall) konfigüre ederken /api/users, /api/orders, /api/products gibi endpoint’leri ayrı ayrı izleyebilir, her biri için farklı rate limit kuralları yazabilirsiniz. Güvenlik politikalarınız granüler düzeyde kalır.
Dezavantajı ise saldırı yüzeyinin görünürlüğüyle ilgili. Bir saldırgan /api/v1/users/123/orders/456/items gibi bir endpoint’i keşfedince ne yapabileceğini tahmin edebilir. Endpoint enumeration saldırıları REST’te oldukça yaygındır.
Kimlik Doğrulama ve Yetkilendirme
REST’te en yaygın kimlik doğrulama yöntemleri JWT ve OAuth 2.0’dır. Temel bir JWT middleware örneği:
# Express.js tabanlı bir REST API için JWT doğrulama testi
curl -X GET https://api.sirketim.com/api/v1/users
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
-H "Content-Type: application/json"
-v
Peki JWT implementasyonunda ne gibi hatalar yapılır? En yaygın sorun “alg: none” saldırısı. Bazı kütüphaneler algoritma değerini token içinden okursa, saldırgan imzayı tamamen devre dışı bırakabilir.
# JWT token decode ederek payload kontrol
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U" |
cut -d'.' -f2 |
base64 -d 2>/dev/null |
python3 -m json.tool
# JWT secret brute force kontrolü için basit test (pentest senaryosu)
# jwt_tool kullanarak zayıf secret tespiti
python3 jwt_tool.py eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIn0.xxx
-C -d /usr/share/wordlists/rockyou.txt
REST’te BOLA ve Broken Object Level Authorization
OWASP API Security Top 10’un başında gelen BOLA (Broken Object Level Authorization), REST API’lerde kritik bir güvenlik açığıdır. Klasik senaryo şu:
Kullanıcı kendi siparişini görmek için /api/orders/1001 isteği gönderir. Sisteminiz sadece JWT token’ın geçerliliğini doğruluyorsa ama “bu token sahibi gerçekten order 1001’in sahibi mi?” kontrolü yapmıyorsa, kullanıcı /api/orders/1002, /api/orders/1003 diyerek başkalarının verilerine erişebilir.
# BOLA testi için basit bir Bash script
#!/bin/bash
TOKEN="Bearer eyJhbGci..."
BASE_URL="https://api.sirketim.com"
for order_id in $(seq 1000 1010); do
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}"
-H "Authorization: $TOKEN"
"$BASE_URL/api/orders/$order_id")
if [ "$RESPONSE" == "200" ]; then
echo "[ALERT] Order $order_id erişilebilir - BOLA açığı olabilir!"
fi
done
GraphQL Güvenliği: Farklı Bir Dünya
GraphQL, tek endpoint (/graphql) üzerinden çalışır. İstemci tam olarak neye ihtiyacı olduğunu belirtir ve sunucu bunu döner. Bu esneklik, güvenlik açısından bambaşka riskler barındırır.
Introspection: Çift Taraflı Kılıç
GraphQL’in en güçlü özelliği aynı zamanda en büyük güvenlik sorunudur: Introspection. Introspection sayesinde herhangi biri API’nizin tam şemasını sorgulayabilir.
# GraphQL introspection sorgusu ile şema keşfi
curl -X POST https://api.sirketim.com/graphql
-H "Content-Type: application/json"
-d '{
"query": "{ __schema { types { name fields { name type { name } } } } }"
}' | python3 -m json.tool
Bu sorgu production ortamında çalışıyorsa, saldırgan tüm tiplerinizi, alanlarınızı ve ilişkilerinizi öğrenir. REST API’de endpoint enumeration için saatler harcaması gereken bir saldırgan, GraphQL’de bunu saniyeler içinde yapar.
Production ortamında introspection’ı kapatmak zorunludur:
# Apollo Server için introspection kapatma kontrolü
# nginx log'larında introspection sorgu tespiti
grep -E '"__schema"|"__type"' /var/log/nginx/api_access.log |
awk '{print $1, $7}' |
sort | uniq -c | sort -rn | head -20
GraphQL’e Özgü Saldırılar
Depth Attack (Derinlik Saldırısı): GraphQL’in iç içe sorgulara izin vermesi, özyinelemeli sorgularla sunucuyu çökertmek için kullanılabilir. Şöyle düşünün: Kullanıcıların arkadaşları var, arkadaşların da arkadaşları var…
# Zararlı bir depth query örneği (test amaçlı)
curl -X POST https://api.sirketim.com/graphql
-H "Content-Type: application/json"
-d '{
"query": "{ user { friends { friends { friends { friends { friends { name email phone } } } } } } }"
}'
Bu tek bir sorgu, veritabanında onlarca JOIN operasyonunu tetikleyebilir. Buna N+1 query bombing da denir ve DoS saldırısı olarak kullanılır.
Batching Attack: GraphQL, tek HTTP isteğinde birden fazla sorguyu çalıştırabilir. Rate limiting’iniz istek başına hesaplanıyorsa, saldırgan tek bir istek içinde yüzlerce sorgu gönderebilir.
# GraphQL batching attack örneği
curl -X POST https://api.sirketim.com/graphql
-H "Content-Type: application/json"
-d '[
{"query": "{ user(id: 1) { email } }"},
{"query": "{ user(id: 2) { email } }"},
{"query": "{ user(id: 3) { email } }"},
{"query": "{ user(id: 4) { email } }"}
]'
Güvenlik Kontrollerinin Karşılaştırması
Rate Limiting
REST’te rate limiting oldukça straightforward’dur. Nginx veya bir API gateway üzerinde endpoint bazlı kurallar yazarsınız:
# Nginx'te REST API rate limiting konfigürasyonu
cat << 'EOF' > /etc/nginx/conf.d/api_ratelimit.conf
# Rate limit zone tanımları
limit_req_zone $binary_remote_addr zone=api_general:10m rate=100r/m;
limit_req_zone $binary_remote_addr zone=api_auth:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api_sensitive:10m rate=20r/m;
server {
listen 443 ssl;
server_name api.sirketim.com;
# Genel API endpoint'leri
location /api/ {
limit_req zone=api_general burst=20 nodelay;
proxy_pass http://backend;
}
# Auth endpoint'leri daha kısıtlı
location /api/auth/ {
limit_req zone=api_auth burst=5 nodelay;
proxy_pass http://backend;
}
}
EOF
nginx -t && systemctl reload nginx
GraphQL’de ise tek endpoint olduğu için IP bazlı rate limiting yetersiz kalır. Query complexity scoring sistemi kurmanız gerekir:
# GraphQL query complexity analizi için log parsing
# Her sorgunun ne kadar karmaşık olduğunu ölçmek için
tail -f /var/log/app/graphql.log |
python3 -c "
import sys, json, re
for line in sys.stdin:
try:
log = json.loads(line)
query = log.get('query', '')
# Basit complexity: field sayısı + nesting derinliği
fields = len(re.findall(r'w+s*{', query))
depth = max(len(m) for m in re.findall(r'{+', query)) if query else 0
complexity = fields * depth
if complexity > 50:
print(f'[HIGH COMPLEXITY] Score: {complexity} | IP: {log.get("ip", "unknown")}')
except:
pass
"
OWASP API Security Top 10 Perspektifinden
Excessive Data Exposure açısından iki mimari arasında ciddi bir fark var. REST’te backend ne dönerse istemci onu alır. Bir endpoint gereğinden fazla alan döndürüyorsa bu veri her zaman istemciye gelir. GraphQL’de ise istemci tam olarak ne istediğini belirtir. Ama bu da bir risk içerir: Yetersiz alan seviyesi yetkilendirme varsa, hassas alanlar istenebilir.
# REST API'de excessive data exposure tespiti
# Response boyutlarını izleyerek anormal durumları tespit et
curl -s -w "n%{size_download}"
-H "Authorization: Bearer $TOKEN"
https://api.sirketim.com/api/users/me |
tail -1 |
awk '{ if ($1 > 5000) print "UYARI: Response boyutu anormal: " $1 " byte" }'
Input Validation ve Injection Saldırıları
Her iki mimaride de SQL injection ve diğer injection saldırıları temel tehdittir. Ancak GraphQL’de saldırı vektörleri biraz farklıdır.
REST’te input validation nispeten basittir. Belirli endpoint’ler belirli parametreler alır, bunları şema ile doğrularsınız.
GraphQL’de ise dinamik sorgu yapısı nedeniyle validation daha karmaşıktır. Özellikle directive injection ve fragment injection dikkat edilmesi gereken noktalardır:
# GraphQL injection test senaryosu
# Argument değerlerine SQL injection denemesi
curl -X POST https://api.sirketim.com/graphql
-H "Content-Type: application/json"
-H "Authorization: Bearer $TOKEN"
-d '{
"query": "{ users(filter: "1=1 OR 1=1") { id email } }"
}'
-w "nHTTP Status: %{http_code}n"
# WAF'ın bu isteği bloklaması beklenir
# 403 dönüyorsa WAF çalışıyor demektir
Pratik Güvenlik Önlemleri: Her İkisi İçin
API Gateway Kullanımı
Production ortamında ne REST ne de GraphQL’i direkt internete açmamalısınız. Kong, AWS API Gateway veya Traefik gibi bir API gateway katmanı zorunludur.
# Kong ile JWT plugin aktifleştirme ve rate limiting
# REST API için service oluşturma
curl -X POST http://localhost:8001/services
-d name=user-service
-d url=http://backend:3000
# Route ekleme
curl -X POST http://localhost:8001/services/user-service/routes
-d "paths[]=/api/v1/users"
# JWT plugin aktifleştirme
curl -X POST http://localhost:8001/services/user-service/plugins
-d name=jwt
# Rate limiting plugin
curl -X POST http://localhost:8001/services/user-service/plugins
-d name=rate-limiting
-d config.minute=100
-d config.hour=1000
-d config.policy=local
TLS ve Sertifika Yönetimi
Her iki mimari için de TLS 1.2 ve üzeri zorunludur. Zayıf cipher suite’leri devre dışı bırakmak kritik önem taşır:
# OpenSSL ile API endpoint TLS güvenliğini kontrol et
openssl s_client -connect api.sirketim.com:443
-tls1_2
-servername api.sirketim.com 2>/dev/null |
grep -E "Protocol|Cipher|Verify"
# Zayıf cipher kontrolü
nmap --script ssl-enum-ciphers
-p 443 api.sirketim.com |
grep -E "WEAK|SSLv|TLSv1.0|TLSv1.1"
# Güçlü cipher suite listesi için nginx ssl_ciphers ayarı
echo "ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;" |
sudo tee -a /etc/nginx/snippets/ssl-params.conf
Audit Logging
Her iki mimaride de kapsamlı audit log tutmak zorunludur. Ancak GraphQL loglama biraz daha dikkat ister çünkü tüm istekler aynı endpoint’e gider ve query içeriğini loglamak gerekir.
# GraphQL audit log analizi
# Son 1 saatte en çok mutation yapan IP'leri bul
awk -v date="$(date -d '1 hour ago' +'%Y-%m-%dT%H:%M')"
'$0 > date && /mutation/'
/var/log/app/graphql_audit.log |
grep -oP '"ip":"[^"]*"' |
sort | uniq -c | sort -rn | head -10
Güvenlik Monitoring ve Alerting
İki mimariyi de izlemek için farklı stratejiler gerekir. REST’te anormallik tespiti endpoint bazında yapılabilirken, GraphQL’de query pattern analizi yapılması gerekir.
# REST API için anomaly detection script
#!/bin/bash
# Son 5 dakikada belirli bir endpoint'e anormal istek sayısı kontrolü
THRESHOLD=500
ENDPOINT="/api/v1/users"
TIMEFRAME=5 # dakika
COUNT=$(grep "$(date +'%d/%b/%Y:%H')" /var/log/nginx/api_access.log |
grep "$ENDPOINT" |
wc -l)
if [ "$COUNT" -gt "$THRESHOLD" ]; then
echo "ALERT: $ENDPOINT son ${TIMEFRAME} dakikada $COUNT istek aldı!" |
mail -s "API Anomaly Alert" [email protected]
# Kaynak IP'leri logla
grep "$ENDPOINT" /var/log/nginx/api_access.log |
awk '{print $1}' | sort | uniq -c | sort -rn | head -5 >>
/var/log/alerts/api_anomaly_$(date +'%Y%m%d_%H%M').log
fi
Hangisini Tercih Etmeli?
Güvenlik perspektifinden bakıldığında iki mimari arasındaki temel farklar şöyle özetlenebilir:
REST API güvenlik avantajları:
- Tahmin edilebilir endpoint yapısı WAF konfigürasyonunu kolaylaştırır
- HTTP metodları semantik ayrım sağlar (GET, POST, PUT, DELETE)
- Endpoint bazlı granüler rate limiting mümkündür
- Saldırı yüzeyi daha kolay haritalanır
- Mevcut güvenlik araçları ve pratikler çok daha olgunlaşmıştır
GraphQL güvenlik avantajları:
- İstemci sadece ihtiyacı olan veriyi ister, over-fetching azalır
- Güçlü tip sistemi otomatik input validation sağlar
- Tek endpoint, ağ seviyesinde saldırı yüzeyini daraltır
- Versiyonlama gerektirmemesi eski zayıf endpoint’lerin hayatta kalmamasını sağlar
GraphQL’e özgü riskler:
- Introspection ile şema tamamen ifşa edilebilir
- Derinlik ve karmaşıklık saldırıları servis dışı bırakabilir
- Batching saldırıları rate limiting’i bypass edebilir
- Granüler endpoint yetkilendirmesi yoktur, field seviyesinde yetkilendirme yapılmalıdır
Hangi mimariyi seçerseniz seçin, güvenlik sonradan eklenen bir katman değil, tasarımın içine işlemiş bir bileşen olmak zorundadır. Bir sysadmin olarak “benim işim sadece sunucuyu ayakta tutmak” deme lüksünüz yok. Artık API katmanının güvenliğini da anlamanız, monitor etmeniz ve gerektiğinde müdahale edebilmeniz bekleniyor.
Sonuç
REST vs GraphQL güvenlik tartışması “hangisi daha güvenli?” sorusuna indirgenemez. İkisi de güvenli veya güvensiz olabilir; fark sizin nasıl implemente ettiğinizde yatar.
REST için temel öncelikleriniz; sağlam BOLA/BFLA kontrolleri, endpoint bazlı rate limiting, JWT implementasyon güvenliği ve tutarlı input validation olmalıdır.
GraphQL için ise üretim ortamında introspection’ı kapatmak, query complexity limitleri koymak, derinlik kısıtlaması uygulamak, batching saldırılarına karşı önlem almak ve field seviyesinde yetkilendirme sağlamak öncelikli maddeler arasında yer alır.
Her iki durumda da bir API gateway arkasında çalışmak, kapsamlı audit logging yapmak, düzenli penetrasyon testleri uygulamak ve OWASP API Security Top 10’u baz alan bir güvenlik değerlendirmesi yapmak kritik öneme sahiptir. Güvenlik bir ürün değil, bir süreçtir ve bu süreç her deployment’ta, her konfigürasyon değişikliğinde ve her yeni özellik eklenmesinde yeniden gözden geçirilmelidir.
