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.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir