Saldırı altında mısınız? Olay müdahalesi için bize ulaşın

Güvenli yazılım geliştirme

GraphQL API güvenliği: yayına almadan önce çalıştırılacak beş test

Staging'de çalıştırın: varsayılan ayarlar, girdi doğrulama, sorgu maliyeti, batching istismarı ve alan bazlı yetkilendirme testleri ve çözümleri.

Diğer diller:EnglishDeutschFrançaisEspañolItalianoPolskiNederlandsEesti

İllüstrasyon: GraphQL API güvenliği: yayına almadan önce çalıştırılacak beş test

Endpoint herkese açılmadan önce bu beş testi GraphQL API'nizin staging ortamındaki dağıtımına karşı çalıştırın. Staging'i production'ın olacağı şekilde yapılandırın, aksi halde sonuçların pek bir anlamı kalmaz.

Testler, OWASP GraphQL Cheat Sheet belgesindeki dört alanı izler: girdi doğrulama, maliyetli sorgular, erişim kontrolü ve güvensiz varsayılan yapılandırma.

1. Varsayılan ayarları kontrol edin

Aşırı ayrıntılı hata mesajları, introspection ve GraphiQL, en sık karşılaşılan güvensiz varsayılanlardır. Üçünü de test edin. En küçük introspection sorgusuyla başlayın:

{__schema{types{name}}}

Sunucunun şema ayrıntılarıyla yanıt verip vermediğine ya da isteği reddedip reddetmediğine bakın. Ardından tarayıcıda GraphiQL arayüzünü arayın. Son olarak hatalı biçimlendirilmiş bir sorgu ve geçersiz argümanlı bir sorgu gönderip hata mesajını okuyun. Yanıtta resolver adları, stack trace'ler veya veritabanı mesajları görünüyorsa, bunlar saldırgan için bir harita işlevi görür.

Çözüm yapılandırmadadır. API'nin keşfedilmesi amaçlanmıyorsa introspection'ı ve GraphiQL'i kapatın, genel nitelikte hata mesajları döndürün ve ayrıntıyı sunucu tarafındaki loglarda tutun.

2. Her argümana hatalı ve zararlı girdi gönderin

Kimlik bilgilerini (identifier) kullanıcı sağlar, veri çekiciler (data fetcher) de bunları HTTP isteklerinde, veritabanı sorgularında ve diğer çağrılarda kullanır. Injection tam olarak burada ortaya çıkar. Her query ve mutation'ın her argümanını, başka herhangi bir API'de kullanacağınız payload'larla test edin: SQL ve NoSQL injection, işletim sistemi komut injection'ı, SSRF ve CRLF injection.

Bunu betiklenebilir hale getirmek için, staging'de introspection hâlâ açıkken argüman listelerini şemadan üretin, payload'larınızı bu listeler üzerinde döngüyle çalıştırın ve ardından introspection'ı kapatın.

Uygulanması gerekenler:

  • Skaler ve enum gibi belirli GraphQL tipleri ile mutation girdisi için tanımlı şemalar.
  • Engelleme listesi (denylist) yerine izin listesi (allowlist) kullanımı. Alfanümerik, unicode içermeyen girdi iyi bir başlangıç noktasıdır, çünkü birçok saldırıyı baştan eler.
  • Bir yorumlayıcıya (interpreter) iletilen her şey için parametreli ifadeler. ORM veya ODM kullanıyorsanız dokümantasyonda anlatıldığı şekilde kullanın, çünkü ORM injection hâlâ mümkündür.
  • Geçersiz girdinin, doğrulamanın nasıl çalıştığını belli etmeden reddedilmesi.

3. Maliyetli sorguyu bulun

Herhangi bir kaynak limiti eksikse veya yanlış ayarlanmışsa API savunmasızdır. OWASP'ın unrestricted resource consumption maddesi şunları sayar: yürütme zaman aşımları, ayrılabilecek azami bellek, dosya tanımlayıcıları, süreçler, yüklenen dosya boyutu, sayfa başına kayıt sayısı, istemci isteği başına işlem sayısı ve üçüncü taraf sağlayıcılardaki harcama limitleri.

Test için, ilişkileri bir döngüyle izleyerek şemanızın izin verdiği en derin sorguyu oluşturun. İsimleri kendi şemanıza göre uyarlayın:

{ users { orders { customer { orders { customer { email } } } } } }

Sunucu reddedene ya da yavaşlayana kadar seviye eklemeye devam edin. Sonra çok büyük bir sayfa boyutu isteyin ve aşırı büyük bir payload gönderin.

Cheat sheet'in önerisi, çok maliyetli sorguları sınırlayan veya engelleyen kontroller eklemektir. Bunu sayfa boyutu üst sınırı, yürütme zaman aşımı ve string, dizi (array) ve yüklemeler için azami boyutlarla birleştirin. Meşru istemciler bu değerlerin altında kalsın diye değerleri bir haftalık gerçek trafik loglarına bakarak ayarlayın.

4. Batching ile rate limiter'ı aşın

Batching, istek sayısını gizleyen bir brute force yöntemidir. OWASP maddesinin ikinci senaryosunda, bir upload mutation'ı rate limiter ve boyut kontrolünün arkasındadır. Saldırgan /graphql adresine, yaklaşık bin işlemden oluşan bir dizi içeren tek bir POST gönderir. Limiter tek istek görür ve sunucunun belleği tükenir. API'niz dosya yüklemelerini kabul ediyorsa, bu konuyu güvenli dosya yüklemelerini tasarlama ve test etme yazımızda ele alıyoruz.

Aynısını bir login veya OTP mutation'ına karşı deneyin:

[
  {"query": "mutation {login(user: \"alice\", pass: \"guess1\") {token}}"},
  {"query": "mutation {login(user: \"alice\", pass: \"guess2\") {token}}"}
]

Limitinizin dizideki her işlemi sayıp saymadığını ve başarısız denemelerin hesap kilitleme mantığınıza yine de ulaşıp ulaşmadığını kontrol edin. Ardından sunucunuzun birden fazla işlemi tek istekte toplamaya izin verdiği diğer yolları da deneyin.

İstemci isteği başına işlem sayısını sınırlayın ve tek bir istemcinin OTP doğrulama gibi hassas bir işlemi ne sıklıkla çalıştırabileceğini kısıtlayın. Harcamayı da sınırlayın: maddenin ilk senaryosunda bir betik, parolamı unuttum akışı üzerinden on binlerce ücretli SMS tetikler. Üçüncü taraf sağlayıcılar için harcama limitleri belirleyin, limit konulamayan yerlerde ise faturalandırma uyarıları kurun.

5. Başkasının alanını isteyin

Kimlik doğrulama (authentication), çağıranın kim olduğunu söyler. Hangi alanları okuyabileceğine karar vermez. GraphQL yetkilendirme rehberi, yürütmenin kimliği doğrulayan authentication middleware'inden sonra başlaması gerektiğini ve sunucunun yine de istenen her alan için kullanıcının onu görüp göremeyeceğine karar vermesi gerektiğini söyler.

İki sıradan hesapla test edin. A hesabının oturumuyla B hesabının nesnelerini ID'leriyle isteyin, ardından iki hesabın da görebildiği ilişkili bir nesne üzerinden bunlara ulaşmayı deneyin. İsimleri kendi şemanıza göre uyarlayın:

# Direct lookup: should be refused for account A
{ customer(id: "CUSTOMER_ID_OF_B") { email } }

# Same data through a shared parent: must also be refused
{ product(id: "SHARED_PRODUCT_ID") { orders { customer { email } } } }

İlk sorgu reddedilip ikincisi B'nin e-postasını döndürüyorsa, kontrol yalnızca üst düzey lookup'ta bulunuyor ve iç içe geçmiş tipe hiç uygulanmamış demektir. Aynı testi hiç oturum olmadan da tekrarlayın. Aynı veri REST veya mobil API üzerinden de sunuluyorsa, bu giriş noktalarını da test edin. Uygulamanızdaki her ID'yi IDOR ve BOLA için test etme yazımız aynı yaklaşımı GraphQL'in ötesinde de ele alıyor.

Field resolver içindeki yetkilendirme prototipler için yeterlidir, ancak her giriş noktası için kopyalamanız gerekir. Kopyalar birbirinden ayrışırsa kullanıcılar hangi API'yi kullandıklarına göre farklı veriler görür. Mantığı iş mantığı katmanına taşıyın, böylece tek bir doğruluk kaynağı olur. Rehberdeki örnekte postRepository.getBody, kullanıcıyı ve gönderiyi alır, gövdeyi yalnızca yazara döndürür. Opak bir token veya API anahtarı değil, tam olarak doldurulmuş bir kullanıcı nesnesi iletin.

Bir tarayıcının size söylemeyeceği şeyler

Otomatik araçlar genişlik sağlar, ancak OWASP Web Security Testing Guide bunların genel olarak uygulamalar için geliştirildiğini, sizin özel kodunuz ve iş kurallarınız için geliştirilmediğini belirtir. En ciddi açıklar çoğu zaman iş mantığıyla iç içe geçmiştir.

1'den 3'e kadar olan testler büyük ölçüde betiklenebilir. 5. test ise manuel çaba gerektirir, çünkü hangi tenant'ın hangi nesneye sahip olduğunu birinin anlaması gerekir. Bu yüzden dışarıdaki bir ekibe devredilmeye en değer olan testtir. Sızma testi hizmetimiz bunu kapsar.

Nereden başlamalı

  1. Staging dağıtımında introspection sorgusunu gönderin ve GraphiQL'i açın. Yanıt veren her şeyi kapatın, ardından hatalı biçimlendirilmiş bir sorguyla yeniden test edip hata mesajlarını kontrol edin.
  2. Tüm query ve mutation argümanlarını listeleyin. Her birinin belirli bir tipi veya enum'u ve bir izin listesi doğrulayıcısı olduğundan emin olun.
  3. Derin iç içe sorguyu, büyük sayfa boyutlu bir isteği ve aşırı büyük bir payload'u gönderin. Limitleri ayarlayın, ardından sorguları yeniden gönderip her birinin reddedildiğini doğrulayın.
  4. Login ve OTP mutation'larınıza karşı dizi halinde batch gönderin. İstek başına bir limit ve hassas işlemlerin tekrarı için bir kısıt uygulayın.
  5. Kişisel veya ticari veri tutan her tipte, iç içe ilişkiler dahil iki hesaplı testi çalıştırın. Bir resolver içinde bulduğunuz her kontrolü iş mantığı katmanına taşıyın.

Nasıl yardımcı olabiliriz

Sızma testi

Ağlarınıza, uygulamalarınıza ve çalışanlarınıza gerçek bir saldırgan gibi saldırır, her açığı nasıl kapatacağınızı gösteririz.

Bize yazın
AngelForce ekibi

Bu yazıyı AngelForce ekibi hazırladı: Avrupa genelindeki kurumların sistemlerini test eden, izleyen ve koruyan; CEH, LPT Master ve CISA sertifikalı güvenlik danışmanları.

Aşağıda listelenen herkese açık kaynaklardan yapay zekâ desteğiyle yazıldı ve yayından önce AngelForce ekibi tarafından incelendi.

Kaynaklar

  1. cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html
  2. api-security.owasp.org/editions/2023/en/0xa4-unrestricted-resource-consumption/
  3. graphql.org/learn/authorization/
  4. wstg.owasp.org/latest/

Güvenli yazılım geliştirme hakkında yazılar

Neyi korumanız gerektiğini anlatın

Altyapınızı ve hedefinizi kısaca yazın, size e-postayla dönelim.

Bize yazın
info@angelforce.eu +372 5705 2044

AngelForce OÜ · Tallinn, Estonya