
GraphQL Hacking 101: Saldırganın Gözünden Zafiyetler
Günümüz uygulamalarında API'lerle haberleşme her zamankinden daha kritik bir hale geldi. Bu ihtiyacı karşılamak için REST gibi köklü çözümlerin yanı sıra GraphQL gibi yeni ve esnek teknolojiler de hayatımıza girdi. Bu yazıda, özellikle GraphQL'e odak...
Günümüz uygulamalarında API'lerle haberleşme her zamankinden daha kritik bir hale geldi. Bu ihtiyacı karşılamak için REST gibi köklü çözümlerin yanı sıra GraphQL gibi yeni ve esnek teknolojiler de hayatımıza girdi. Bu yazıda, özellikle GraphQL'e odaklanacak ve bir bug bounty avcısının, siber güvenlik araştırmacısının ya da bir saldırganın gözünden bu teknolojideki zafiyetlerin nasıl sömürüldüğünü anlamaya çalışacağız. Gelin, bu önemli konuya birlikte bakalım.
Başlamadan önce belirtmek isterim ki, bu yazıdaki tüm örnekler ve ekran görüntüleri kontrollü bir sandbox ortamında, tamamen eğitim amacıyla gerçekleştirilmiştir. Hiçbir canlı sisteme zarar verilmemiştir. Buradaki amacımız saldırgan bir yaklaşımı teşvik etmek değil, tam aksine, saldırganların nasıl düşündüğünü ve hareket ettiğini anlayarak daha güvenli sistemler inşa edebilmektir. Savunmanın ilk adımı, potansiyel saldırı vektörlerini bilmektir.
GraphQL Nedir ve Nerede, Neden Kullanılır?
GraphQl Nedir?
GraphQL, Facebook tarafından geliştirilen ve 2015 yılında açık kaynak olarak sunulan bir sorgu dilidir.
REST API'lere alternatif olarak geliştirilmiş olup, istemcilerin ihtiyaç duydukları verileri daha esnek ve verimli bir şekilde sorgulamalarına olanak tanır.
Temel Özellikler
Esneklik: İstemciler, ihtiyaç duydukları belirli veri parçalarını sorgulayabilirler.
Verimlilik: Tek bir istekle birden fazla kaynaktan veri alınabilir.
Tip Güvenliği: GraphQL şeması, veri türlerini ve ilişkileri tanımlar, bu da istemcilerin hangi verilere erişebileceğini önceden bilmesini sağlar.
GraphQL'in neden önemli olduğunu anlamamız için nerede ve neden kullanıldığını anlamamız gerekiyor.
Bundan dolayı aşağıda yazacağım alanları okumanızı ve anlamlandırmanız için kendi içinizde sorgulamanızı istiyorum.
GraphQL mobil ve web tarafında yaygın bir şekilde kullanılır.
GraphQL, REST API'lerinde istemcilerin genellikle ihtiyaç duymadıkları büyük veri blokları almasının önüne geçerek yalnızca gerekli veri parçalarını çekmelerine olanak tanıdığı için tercih edilir. Ayrıca, farklı kaynaklardan gelen verileri tek bir sorguda birleştirebilmesi, API'lerin self-documenting (kendini belgeleyen) yapısıyla entegrasyonun kolaylaşması, güçlü geliştirici araçları sunması ve istemcilerin verileri belirli parçalara ayırarak sorgulamalarına imkan tanıyarak veri aktarımını ve işleme sürelerini optimize etmesi gibi özellikleriyle öne çıkar.
Temel Sorgular
GraphQL, sorguları için genellikle GET ve POST yöntemlerini destekler. Bu sorgulardan biri olan Introspection, şema bilgilerini ortaya çıkarmak için kullanılır ve bir saldırganın hedef sistemin yapısını anlamasına yardımcı olur. Geliştirme aşamasında bu paha biçilmez bir araç olsa da, production (canlı) ortamında aktif bırakıldığında, bir saldırgana tüm API'nin haritasını, olası zayıf noktalarını ve veri yapılarını kendi ellerinizle teslim etmek anlamına gelir. Saldırganın gözünden bakınca, introspection sorguları tam bir keşif hazinesi gibi; API'nin veri türlerini, alanlarını, argümanlarını ve ilişkilerini tanımlayan şemayı ele geçirerek, hassas verilere giden yolları kolayca belirleyebilirsin. Bu sayede, keşif aşamasında etkili saldırılar planlamak çok daha basit hale geliyor, mesela yetkisiz veri çekme veya DoS atakları için. Genellikle geliştiriciler production'da bunu devre dışı bırakmayı atlıyor ya da anonim erişime açık API'lerde kontroller yetersiz kalıyor. Benzer bir sıkıntı Red Hat GraphQL'de CVE-2024-50312 olarak yaşanmış, yetkisiz kullanıcılar şema bilgilerine ulaşabilmiş. Parse Server'daki CVE-2025-53364 ise devre dışı bırakmanın bile bazen yetersiz kaldığını gösteriyor.
Örnek sorgular
Tüm tiplerin adlarını bulmak için:
{__schema{types{name}}}
Tüm alanlar ve argümanları listelemek için:
{ __schema { types { name fields { name args { name description type { name kind } } } } } }
Hataları İnceleme
Hata mesajları, sistem hakkında önemli ipuçları verebilir.
Hata mesajlarını tetiklemek için geçersiz sorgular gönderme:
{olmayanbirdeger}
Saldırgan açısından hata inceleme, bilgi sızıntısının kapısını aralıyor; geçersiz sorgularla sunucunun verdiği detaylı mesajlar veritabanı türü, kütüphane versiyonu gibi sırları ortaya döküyor. Bu da daha karmaşık ataklar için mükemmel bir zemin hazırlıyor, örneğin SQL injection'ları test ederken başarıyı hemen görmek gibi. Production'da hata mesajları gizlenmemişse veya geliştirme ayarları canlıya taşınmışsa bu tür sorunlar sık çıkıyor. GitLab'daki CVE-2021-4191, GraphQL API'lerde bilgi sızıntısının kullanıcı bilgilerini nasıl enumerate ettiğinin güzel bir örneği.
Veri Çıkarma
Şemayı ve alanları öğrendikten sonra, veri çıkarma işlemleri yapılabilir. Örneğin, bir "user" nesnesi varsa, değerlerini almak için şu sorgu kullanılabilir:
{ user(id: "1") { id name email } }
Veri çıkarma, introspection sonrası "hasat" aşamasıdır. Saldırgan, şemadan öğrendiği alanları sorgulayarak hassas verileri (e-posta, şifre hash'leri) çeker. Bu, kimlik avı veya daha büyük saldırılar için kullanılır. Örneğin, kullanıcı ID'lerini enumerate ederek (1'den başlayarak artırmak) veritabanı dökümü yapılabilir. Erişim kontrolleri yetersizse, anonim sorgulara izin veriliyorsa veya IDOR zafiyeti varsa bu mümkün olur. Bununla ilgili daha önceden GitLab’da ortaya çıkan CVE-2021-4191 zafiyetini inceleyebilirsiniz.
Saldırı Vektörleri
Yetkilendirme ve Kimlik Doğrulama (Authorization and Authentication)
GraphQL API'leri, REST API'lerine göre daha ince taneli veri erişim kontrolüne ihtiyaç duyar. Yanlış yapılandırılmış yetkilendirme, kullanıcıların yetkileri dışında verilere erişmesine neden olabilir. Örneğin, konunun öncesinde bahsettiğim sorgu ile kullanıcılara erişmeyi deneyebilirsiniz.
query { user(id: "123") { id username email } }
Bu vektör, saldırgan için tam bir yetki yükseltme fırsatı. GraphQL'in esnekliği yüzünden belirli alanlara kontrol koymak zorlaşıyor; böylece saldırgan kendi yetkisi dışındaki verilere, mesela admin e-postalarına ulaşabiliyor. Alan bazlı yetkilendirme eksikse ya da token doğrulama yetersizse, özellikle global auth kullanılmayan sistemlerde bu sorun patlak veriyor. Benzer bir durum GraphQL endpoint'lerinde CVE-2025-31481 ile yaşanmış; Relay node type'ı kullanarak kontrolleri bypass ediyor ve yetkisiz sorgulara yol açıyor.
Batch Querying ve Denial of Service (DoS) Saldırıları
GraphQL, tek bir istekte birden fazla sorgunun yapılmasına izin verir. Bu özellik, saldırganların sunucuyu aşırı yüklemesine neden olabilir.
Yani, sunucuyu daha fazla veri döndürmesine zorlayabilirsiniz.
query { nestedField1 { nestedField2 { nestedField3 { nestedField4 { ... } } } } }
Bu tür bir sorgu, sunucunun işleme kapasitesini zorlayarak hizmet reddi saldırısına yol açabilir. Saldırgan açısından batch querying, kaynakları kurutmanın kolay yolu; birden fazla sorguyu tek istekte birleştirerek CPU veya RAM'i bitiriyor, sunucuyu yavaşlatıp çökertiyor. Rakip siteleri offline etmek veya fidye istemek için sık kullanılıyor. Query batching sınırlanmamışsa, rate limiting veya complexity limit yoksa bu ataklar kaçınılmaz. Directus'taki CVE-2024-39895, alan duplikasyonuyla benzer bir DoS'a örnek.
Mass Assignment (Toplu Atama) Saldırıları
GraphQL API'leri, istemcilerin veri yapısını belirlemesine izin verir. Bunu yapmak için genellikle mutation komutlarını kullanırız. Böylece yetkisiz alanlara veri ekleyebiliriz.
mutation { updateUser(id: "2", input: {role: "admin"}) { id name role } }
Bu sorgu, bir kullanıcının yetkisiz bir şekilde yönetici rolüne yükseltilmesine neden olabilir. Saldırgan için mass assignment, veri manipülasyonunun anahtarı; mutation'larda input'ları doldurarak yetkisiz özellikleri değiştiriyor. Input validation eksikse, whitelist yerine blacklist kullanıldığında bu tür açıklar çıkıyor. Parse Server'daki CVE-2025-53364, schema yüklemede benzer manipülasyonlara yol açıyor.
Injection Saldırıları
GraphQL sorguları, doğrudan veritabanı işlemlerine dönüşür. Bu, SQL enjeksiyonu gibi klasik saldırılara açık olabilir.
{ userByUsername(username: "" OR 1=1 --") { id name email } }
Injection, saldırganın kod enjekte ederek veritabanını ele geçirme aracı; girdiler sanitize edilmezse SQL/NoSQL komutları sokulup tüm veri dökülebiliyor. Argüman sanitization eksikse veya ORM kullanılmıyorsa bu sorunlar baş gösteriyor. GraphQL-Ruby'deki CVE-2025-27407, untrusted schema yüklemeyle benzer injection'lara örnek.
"Deep Query" (Derin Sorgu) Saldırısı
Derin sorgu saldırısı, kötü niyetli bir kullanıcının çok derin ilişkili sorgular göndererek sunucunun aşırı yüklenmesini sağlar.
{ userWithFriends(id: "1") { name friends { name friends { name friends { name friends { name } } } } } }
Deep query, saldırganın recursive sorgularla sunucuyu kilitleme taktiği; ilişkileri derinleştirerek veritabanı yükünü katlıyor. Query depth limit yoksa veya recursive ilişkiler sınırsızsa kaçınılmaz. Apollo Gateway'deki CVE-2025-32031, deeply nested fragments ile pahalı sorgulara yol açıyor.
Over-fetching ve Under-fetching Saldırıları
GraphQL'in en büyük avantajlarından biri, istemcilerin tam olarak ihtiyaç duydukları veriyi alabilmeleridir. Ancak, bu esneklik kötüye kullanılabilir.
{ users { id name email role friends { id name email friends { name email } } } blogs { id title content author { id name email role } } }
Bu sorgu, tek bir kullanıcı hakkında çok fazla bilgi çekerek sunucu kaynaklarını tüketebilir. Over-fetching saldırıları, hizmet reddi (DoS) saldırılarına yol açabilir. Saldırgan için over-fetching, fazla veri çekerek kaynakları kurutmanın yolu; sunucuyu yorup DoS veya sızıntı yaratıyor. Complexity limit veya field cost hesaplaması yoksa bu ataklar kolaylaşıyor. Apollo Gateway'deki CVE-2025-32031, derin sorgularla benzer over-fetching'e kapı açıyor.
Stored XSS
Zafiyet, komutların hedef sunucuda kalıcı olarak saklanması ve daha sonra kullanıcıya bir web sayfası olarak sunulmasıdır. Örneğin, bir GraphQL mutation kullanılarak sunucuya saklanan ve daha sonra kullanıcıya gönderilen temizlenmemiş girdiler stored XSS saldırılarına yol açabilir.
mutation { createBlog(input: { title: "Test Blog" content: "<script>alert('XSS Vulnerability!')</script>" authorId: "1" }) { id title content } }
Stored XSS, saldırganın mutation ile script sokup kalıcı enjeksiyon yapması; saklanan kod diğer kullanıcılara sunuluyor, cookie çalma veya session hijacking için kullanılıyor. Input sanitization eksikse, mutation'lar girdiyi doğrudan saklıyorsa çıkıyor. Altair GraphQL client'ındaki CVE-2021-41248, benzer stored XSS'e örnek.
OS Command Injection
Bir mutation veya sorgunun kullanıcı girdilerini bir sistem komutunda kullanması durumunda ortaya çıkabilir. Örneğin, sunucu bir URL'den avatar resmi çekmek için kullanıcı girdilerini shell komutlarına (wget, cURL vb.) dahil ettiğinde, yetersiz doğrulama veya temizleme nedeniyle komut enjeksiyonu gerçekleşebilir.
OS command injection, saldırganın girdilerle sistem komutlarını çalıştırma şansı; rm -rf gibi enjekte edip sunucuyu ele geçiriyor. Girdiler doğrudan shell'e geçiriliyorsa ve escaping yoksa çıkıyor. @graphql-tools/git-loader'daki CVE-2021-23326, command injection'a yol açıyor.
Server-Side Request Forgery (SSRF)
Saldırganın kötü niyetli bir GraphQL sorgusu veya mutasyonu sunarak, bir URL'yi değişken veya argüman olarak göndermesiyle gerçekleşebilir. Bu, savunmasız bir sunucu veya sisteme yetkisiz HTTP isteklerinin yapılmasına neden olabilir. Saldırgan için SSRF, dahili ağı taramanın aracı; URL argümanıyla sunucuyu internal kaynaklara zorluyor, cloud metadata çalma veya port scanning için kullanılıyor. URL'ler validate edilmezse, whitelist yoksa, özellikle external fetch mutation'larda çıkıyor. WP-GraphQL'deki CVE-2023-23685, authenticated kullanıcıların SSRF yapmasına izin veriyor.
Yazı boyunca GraphQL'in sunduğu esnekliğin, dikkat edilmediğinde nasıl ciddi güvenlik risklerine yol açabileceğini gördük. Introspection'dan DoS saldırılarına, yetkilendirme atlatma denemelerinden enjeksiyonlara kadar birçok saldırı vektörünü inceledik.
GraphQL, doğru yapılandırıldığında oldukça güçlü bir araç. Ancak her sorgunun, her mutation'un potansiyel bir zafiyet kapısı aralayabileceğini unutmamak gerek. Bu yazıdaki teknikleri kendi testlerinizde başlangıç noktası olarak kullanabilirsiniz. Güvenli kodlamalar.