Neler yeni
Bughane Academy

Bughane Academy, bug bounty, web güvenliği ve sızma testi alanında kendini geliştirmek isteyenler için kurulmuş Türkçe odaklı bir topluluktur.

Burada; gerçek güvenlik açıkları, recon ve exploit teknikleri, payload & bypass yöntemleri, araçlar, scriptler ve write-up’lar topluluk tarafından paylaşılır ve tartışılır.

Birlikte öğren, birlikte üret, birlikte güçlen.

Tek Bir Mutation’dan Tüm Servisin Çökmesine: Bir GraphQL DoS Hikayesi

  • Konuyu Başlatan Konuyu Başlatan k4yra
  • Başlangıç tarihi Başlangıç tarihi

k4yra

Gözlemci
Katılım
11 Ocak 2026
Mesajlar
1
Tepkime puanı
3
Puan
3
Bazen en tehlikeli zafiyetler herhangi bir veri sızdırmaz.

Hassas bilgiler açığa çıkmaz.
Internal servisler ifşa edilmez.

Ama tek bir istek, tüm uygulamayı tamamen kullanılamaz hale getirebilir.

Bu yazıda, basit bir GraphQL özelliğinin nasıl tam kapsamlı bir application-level Denial of Service saldırısına dönüştüğünü anlatıyorum.

dos.jpg

Her Şey Normal Bir Batch Özelliğiyle Başladı


Hedef uygulamada kullanıcıların tek bir shipment üzerinden batch oluşturabildiği bir özellik vardı.

Backend tarafında bu işlem bir GraphQL mutation ile yapılıyordu.

Basitleştirilmiş haliyle şöyle görünüyordu:


JSON:
mutation CreateBatch {
  createBatch(
    warehouseId: "WAREHOUSE_ID",
    presetId: "PRESET_ID"
  ) {
    id
  }
}

Normalde beklenen davranış oldukça basitti:

• Bir mutation çağrısı bir batch oluşturur
• Rate limiting istek bazlı çalışır
• Kötüye kullanım zor görünür

Dışarıdan bakıldığında güvenli bir tasarım gibi duruyordu.



Kırılma Noktası: GraphQL Alias Mekanizması

GraphQL’in güçlü ama çoğu zaman göz ardı edilen bir özelliği vardır: alias’lar.

Bu özellik sayesinde aynı mutation tek bir request içinde birden fazla kez çalıştırılabilir.

Örneğin:


JSON:
mutation CreateBatch {
    a1: createBatch(...) { id }
    a2: createBatch(...) { id }
    a3: createBatch(...) { id }
}

Burada üç farklı alias vardır ama hepsi aynı işlemi yapar.

Ve kritik nokta şuydu:

Rate limiting sadece HTTP isteklerini sayıyordu.
Request içindeki mutation sayısını değil.

Bu da tek bir isteğin yüzlerce operasyon başlatabilmesi anlamına geliyordu.



Basit Ama Yıkıcı Bir Payload

Alias sayısını artırarak payload’ı büyüttüm.

Gerçekte kullandığım yapı buna benziyordu:


JSON:
mutation CreateBatch {
    a1: createBatch(...) { id }
    a2: createBatch(...) { id }
    ...
    a175: createBatch(...) { id }
}

Tek bir HTTP isteği içinde:

175 ayrı batch oluşturma işlemi yer alıyordu.



Etkinin Net Şekilde Ortaya Çıkması

Alias sayısını artırdıkça sunucu yanıt sürelerini ölçtüm.

Ortaya çıkan sonuçlar çok netti:

• 1 alias → yaklaşık 5.5 saniye
• 15 alias → yaklaşık 13.5 saniye
• 78 alias → yaklaşık 58 saniye
• 175 alias → yaklaşık 117 saniye

Alias sayısı arttıkça sunucu ciddi şekilde daha fazla kaynak tüketiyordu.

Bu da her mutation’ın gerçek ve ağır bir işlem olduğunu açıkça gösteriyordu.



Paralel İsteklerle Servisin Çökmesi


Tek bir ağır istek bile sistemi zorlamaya yetiyordu.

Ancak istekler paralel gönderildiğinde etki katlanarak arttı.

75 paralel HTTP isteği gönderdim.
Her biri 175 alias içeriyordu.

Toplamda:

13.125 batch işlemi aynı anda başlatılmış oldu.

Kısa süre içinde uygulama tamamen yanıt veremez hale geldi.

Tarayıcıdan erişmeye çalıştığımda:

Cloudflare 524 timeout hatalarıyla karşılaştım.

Farklı ağlardan ve cihazlardan denediğimde de sonuç değişmedi.

Tüm platform genelinde tam bir servis kesintisi yaşanıyordu.

524.jpg



Arkada Gerçekte Ne Oluyordu?

Sorunun kökeni oldukça basitti:

• Alias sayısına herhangi bir sınır yoktu
• Mutation maliyeti hesaplanmıyordu
• Rate limiting yalnızca istek seviyesindeydi
• Tüm işlemler senkron şekilde yürütülüyordu

Sonuç olarak:

Bir istek yüzlerce ağır işlem başlatıyor
Paralel istekler thread pool’u dolduruyor
Uygulama tamamen kilitleniyordu

Bu bir network saldırısı değildi.

Tamamen uygulama mantığından kaynaklanan bir DoS’tu.

Screenshot 2026-01-29 at 16.04.48.jpg

Nasıl Düzeltildi?


Customer problemi temiz ve etkili bir şekilde çözdü.

Artık her alias çağrısı ayrı bir operasyon olarak sayılıyor.

Yani:

• Rate limiting alias başına uygulanıyor
• Tek request içinde yüzlerce mutation çalıştırmak mümkün değil

Bu sayede:

GraphQL’in esnekliği korunurken
Application-level DoS riski ortadan kaldırılmış oldu.



Bu Bug Neden Önemli?

Bu durum:

• Küçük bir performans yavaşlaması değil
• Geçici bir gecikme değil

Tüm platformun tamamen offline olmasına yol açıyordu.

Ve kolayca tekrarlanabiliyordu.



Çıkarılan Dersler


Bu vaka bana bir kez daha şunu gösterdi:

GraphQL çok güçlüdür, ancak doğru şekilde sınırlandırılmazsa tehlikeli olabilir.

Sadece istek sayısını sınırlamak yeterli değildir.
Her isteğin içinde kaç operasyon çalıştığını da kontrol etmek gerekir.

Alias sayısı, query complexity ve maliyet bazlı kontroller kritik öneme sahiptir.

Ve en önemlisi:

Application-level DoS çoğu zaman hafife alınır.

Ancak etkisi, birçok veri sızıntısından bile daha yıkıcı olabilir.
 
Geri
Üst