<

API Güvenliği 101: Kimlik Doğrulama, Yetkilendirme ve Rate Limiting

Kasım ayının ilk haftasında bir müşterimizden telefon geldi: mobil uygulamalarının aylık altyapı faturası bir önceki aya göre neredeyse üçe katlanmış. Uygulama mağaza sıralamasında yükselmemiş, kampanya yok, kullanıcı artışı mütevazı. Loglara girdik ve tabloyu gördük: trafiğin ezici kısmı gerçek kullanıcılardan değil, API'yi doğrudan döven botlardan geliyordu. Giriş endpoint'inde deneme-yanılma, ürün listesinde veri kazıma, OTP ucunda SMS tetikleme... Uygulamanın arkasındaki API, ortada duran açık büfeydi.

Bu vaka bize şunu bir kez daha hatırlattı: mobil uygulamanızın arkasındaki API, web sitenizden daha büyük bir saldırı yüzeyidir. Çünkü saldırgan tarayıcıyla, arayüzle, butonlarınızla ilgilenmiyor — doğrudan endpoint'lerinize konuşuyor. Uygulama trafiğini bir proxy'den geçirip tüm endpoint'leri çıkarmak beş dakikalık iş; o beş dakikadan sonra API'niz çıplak.

Konu bizim için ayrıca kişisel: araç takip sistemlerimizde binlerce cihaz gece gündüz API'lerimize veri basıyor. Mobil uygulama, web paneli, cihaz telemetrisi, müşteri entegrasyonları — hepsi aynı kapıdan geçiyor ve o kapının güvenliği pazarlık kabul etmiyor. OWASP'ın web listesinden ayrı, sırf API'lere özel bir Top 10 yayınlaması da bu yüzden anlamlı: API güvenliği artık web güvenliğinin dipnotu değil, kendi başına bir disiplin.

Kim olduğunu bilmek, hakkı olduğunu bilmek değildir

API güvenliğinde en pahalı kavram karışıklığıyla başlayayım: kimlik doğrulama ile yetkilendirmeyi eş sanmak. Authentication "sen kimsin?" sorusudur; authorization "senin buna hakkın var mı?" sorusu. İkisi ayrı sorulardır ve ikisinin de her istekte sorulması gerekir.

Token'ı doğrulayıp yetkiyi kontrol etmeyen API'de klasik senaryo şudur: sıradan bir kullanıcı, kendi siparişini çeken isteği yakalar, URL'deki sipariş ID'sini değiştirir ve başkasının siparişini görür. Bu açığın adı BOLA (Broken Object Level Authorization) ve OWASP'ın bu yıl güncellenen API Top 10 listesinde bir numara — tesadüf değil. Denetlediğimiz API'lerde ilk baktığımız şey bu ve maalesef ilk bulduğumuz şey de çoğunlukla bu oluyor. "Token geçerli, devam" diyen her endpoint, potansiyel bir veri sızıntısı noktasıdır.

Çözümün gizemi yok: veri döndüren her endpoint, döndürmeden önce "bu kayıt bu kullanıcının mı / bu kullanıcı bu kayda erişebilir mi" kontrolünü sunucuda yapacak. Sıkıcı, tekrarlı, kahramanlıksız bir iş. Güvenliğin çoğu böyledir.

Buradaki tekrar yükünü hafifletmenin yolu da var: yetki kontrolünü her endpoint'te elle yazmak yerine, merkezi bir katmanda — middleware veya policy yapısında — toplamak. Böylece kural tek yerde yaşar, unutulan endpoint kalmaz ve "yeni gelen arkadaş kontrolü bilmiyordu" cümlesi tarih olur. Denetlediğimiz API'lerde bu katmanın varlığı, genel güvenlik olgunluğunun en hızlı göstergelerinden biri.

Token dediğin nasıl taşınır, nasıl saklanır

Kimlik tarafında pratiğimizi üç maddede özetleyebilirim:

  • Kısa ömürlü access token + refresh token: Access token'ın ömrünü dakikalarla ölçün; çalınırsa hasar penceresi dar kalsın. Uzun ömür işi refresh token'ın ve o da iptal edilebilir olsun.
  • JWT kullanıyorsanız kurallarıyla kullanın: Algoritmayı sunucuda sabitleyin (header'dan algoritma okuyup alg=none yutan kütüphane vakası klasiktir), imzayı her istekte doğrulayın ve içine hassas veri koymayın — JWT şifreli değildir, sadece imzalıdır; payload'ı herkes okuyabilir.
  • Mobilde token güvenli depoda durur: iOS'ta Keychain, Android'de Keystore. SharedPreferences'ta düz metin token, root'lu bir cihazda hediye paketidir.

Bir de şu var: "uygulamanın içine API anahtarı gömeriz, kimse bulamaz" inancı. Bulunuyor. APK açılıyor, string'ler taranıyor, anahtar beş dakikada çıkıyor. İstemciye gömülen hiçbir sır, sır değildir — mimariyi buna göre kurun.

Yetkilendirmenin bir de az bilinen kardeşi var: fazla veri ifşası. Endpoint, ekranda gösterilenden çok daha fazlasını döndürüyorsa — kullanıcı nesnesinin içinde hash'lenmiş şifre, iç notlar, başka kullanıcıların e-postaları — arayüz o alanları göstermese bile saldırgan görür; proxy'de her şey çıplaktır. Aynı ailenin diğer üyesi mass assignment: istemciden gelen JSON'ı olduğu gibi modele yazan API'de, istekli bir kullanıcı gövdeye "role": "admin" ekleyiverir. Çözüm iki yönde de aynı disiplin: giren ve çıkan alanlar için açık listeler. Ne fazlası girer, ne fazlası çıkar.

Rate limiting: en az konuşulan, en çok iş yapan önlem

Yazının başındaki fatura vakasına dönelim, çünkü çözümü tam bu başlıkta. Limitsiz API; brute force için, veri kazıma için, faturanızı şişiren botlar için davetiyedir. O müşteride yaptığımız ilk müdahale katmanlı rate limit oldu: IP başına genel bir tavan, kullanıcı başına ayrı bir tavan ve kritik uçlarda (giriş, OTP, şifre sıfırlama) çok daha sıkı özel limitler. Aşan istek 429 koduyla nazikçe geri çevriliyor.

Sonuç: sadece giriş endpoint'ine konan limit bile sahte deneme trafiğini yüzde 97 düşürdü. Fatura normale döndü, gerçek kullanıcılar hiçbir şey fark etmedi. (Bot operatörü birkaç gün farklı IP'lerle denedi, sonra vazgeçip daha kolay bir hedefe geçti — bu işin doğası bu; kolay hedef olmamak çoğu zaman yeterli.)

Rate limit tasarlarken tek püf noktası şu: limiti yalnızca IP'ye bağlamayın. Botlar IP havuzlarıyla geziyor; kullanıcı/token bazlı ikinci katman şart. Ve limit aşımlarını loglayın — o loglar, kimin kapınızı yokladığının kaydıdır.

Bir de envanter meselesi var — OWASP'ın güncel API listesine girmesi boşuna değil. Sahada en tekinsiz bulgularımız hep aynı türden: dokümantasyonda olmayan ama canlıda çalışan endpoint'ler. Eski mobil sürüm için açılmış, sonra unutulmuş bir v1; test için açılıp kapatılmayan bir uç; "geçici" diye eklenen ve üç yıldır duran bir export servisi. Kimsenin hatırlamadığı endpoint, kimsenin korumadığı endpoint'tir. Altı ayda bir API envanteri çıkarıp "bu uç hâlâ gerekli mi, kim koruyor" diye sormak, yapılabilecek en ucuz denetimlerden biri.

Denetimlerde kullandığımız altı soru

Bir API'yi ilk incelemeye aldığımızda kendimize sorduğumuz soruları sıralayayım; kendi API'niz için bir hızlı test niyetine kullanabilirsiniz. Tüm trafik HTTPS mi, yoksa "içeride nasılsa" diye açık kalan uç var mı? Veri döndüren her endpoint'te nesne seviyesinde yetki kontrolü var mı? Girdi doğrulama sunucuda mı yapılıyor, yoksa mobil uygulamanın terbiyesine mi güvenilmiş? Katmanlı rate limit kurulu mu? Loglar kim-ne zaman-neye erişti sorusuna cevap verebiliyor mu? Ve hata mesajları — stack trace, SQL hatası, iç IP gibi ev sırlarını dışarı sızdırıyor mu?

Bu altı sorunun tamamına gönül rahatlığıyla "evet, kontrol ettik" diyorsanız, saldırganların kolay hedef listesinden çıkmışsınız demektir. Bir kısmında duraksadıysanız — ki telefondaki müşterimiz de duraksamıştı — bir mesaj atın, API'nizi saldırgan gözüyle bir tur gezelim. Bu turun faturası, botların kestiği faturadan her zaman küçük çıkıyor.

📅 Yayınlanma:  ·  Yakup Zengin