Bir GET koleksiyon uç noktasındaki eksik bir güvenlik kontrolü, temel bir CoopCycle hesabına sahip olan herkesin paylaşımlı bir örnekteki tüm mağazaların tam adres defterini çekmesine olanak tanıyarak sayısız müşterinin isimlerini, sokak adreslerini ve posta kodlarını ifşa etti. Hata iki gün içinde yamalandı ve kullanıcıların yayınlanan en son sürüme yükseltmeleri yapmaları önemle rica ediliyor.
Sızıntı nasıl gerçekleşti
Yemek teslimat kooperatifleri tarafından kullanılan açık kaynaklı bir lojistik platformu olan CoopCycle, API'sini PHP framework'ü API Platform ile tanımlar. Bu framework'te her işlem (POST, GET vb.) bir güvenlik ifadesiyle eşleştirilmelidir; eğer ifade atlanırsa, framework kodu herhangi bir yetkilendirme kontrolü yapmadan çalıştırır.
Geliştiriciler, bir mağazanın adres listesini oluşturan veya güncelleyen POST isteğini standart is_granted('edit', object) ifadesiyle korumuşlardı. Bu yöntem işe yarıyor çünkü istek tek bir mağaza varlığını hedefliyor ve framework'e değerlendirmesi için somut bir "nesne" (object) sunuyor.
Aynı kaynağı okuyan GET isteği ise bir koleksiyonu hedefliyor: /api/stores/{id}/addresses. Bir koleksiyon tek bir nesneden oluşmaz, bu nedenle aynı is_granted('edit', object) ifadesi uygulanamaz. Geliştiriciler güvenlik satırını eklemeyi unuttuğu için framework, tenant (kiracı) ayrımı gözetmeksizin adres verilerini kimliği doğrulanmış her kullanıcıya sundu.
Paylaşımlı bir CoopCycle örneğinde, kötü niyetli bir kullanıcı sadece mağaza ID'leri üzerinden döngü kurarak, uç noktaya GET istekleri göndererek ve sistemde kayıtlı her müşterinin ev adreslerini çekerek bu işlemi gerçekleştirebilirdi. Normal bir hesap dışında ekstra bir ayrıcalığa ihtiyaç duyulmadı.
Hata neden fark edilmedi
Sorun basit bir ihmal değildi. API Platform'un bildirimsel güvenlik modeli, "kullanıcının koleksiyondaki her bir nesne ile aynı tenant'a ait olması gerekir" ifadesini belirtmek için doğrudan bir yöntemden yoksundu. Eksik olan kod satırı, tam da framework'ün yetkilendirmeyi zahmetli hale getirdiği noktada yer alıyordu.
Sorunu daha da karmaşık hale getiren durum ise, projenin test paketinin aslında tüm adresleri içeren GET yanıtının beklenen davranış olduğunu doğrulamasıydı. Başka bir deyişle, otomatik testler geçti çünkü testlerde kullanılan fixture'lar (test verileri) tenant'lar arası erişime izin veriyordu ve bu da zafiyeti etkili bir şekilde maskeliyordu. Bu durumda, başarılı (yeşil) bir test paketi sahte bir güvenlik hissi verdi.
Kimler kazandı ve kimler kaybetti
- Müşteriler: Kişisel olarak tanımlanabilir bilgileri (PII) – tam isimleri ve ev adresleri – platformdaki herkese açık hale geldi. Veriler kamuya açık bir şekilde paylaşılmamış olsa bile, ihlal birden fazla kooperatifin gizliliğini tehlikeye attı.
- CoopCycle kullanan kooperatifler: Platformun tenant verilerini koruma yeteneğine olan güven sarsıldı. Henüz güncelleme yapmamış olan her kooperatif, verilerin ifşa edilmeye devam etmesi riskiyle karşı karşıya kaldı.
- CoopCycle bakımcıları: İki gün içinde yama yayınlamaları ve regresyon testleri eklemeleri gibi hızlı tepkileri, sömürü penceresini sınırladı ve sorumlu bir açık kaynak yönetimi sergiledi. Ancak olay, özellikle framework tabanlı varsayılanlar etrafında daha sıkı güvenlik inceleme süreçlerine duyulan ihtiyacı vurguladı.
Geliştiriciler ve denetçiler nelere dikkat etmeli
- İşlem asimetrisi: Bir yol (path) üzerindeki POST (veya herhangi bir değiştirici işlem) korunuyor ancak karşılık gelen GET isteği açıksa, bu tutarsızlık bir uyarı işaretidir. POST isteği, geliştiricilerin kaynağı koruma niyetini ortaya koyar.
- Koleksiyon uç noktaları: Tek bir öğe yerine bir liste döndüren her şey genellikle alışılagelmiş güvenlik modellerinin dışında kalır. Toplu okumalar için yetkilendirme kontrollerinin açıkça eklendiğini doğrulayın.
- Test paketinin gerçekçiliği: Fixture'ların gerçek tenant sınırlarını yansıttığından emin olun. Tenant'lar arası veri sızıntısını doğrulayan başarılı bir test, bir onay ışığı değil, bir uyarı işaretidir.
Düzeltme ve sonraki adımlar
Zafiyet rapor edildikten sonra, CoopCycle çekirdek ekibi GET koleksiyon işlemine eksik güvenlik ifadesini ekledi ve hem tek öğeli hem de koleksiyon uç noktaları için tenant izolasyonunu zorunlu kılan regresyon testlerini devreye aldı. Yama, yazılımın sonraki bir sürümüyle yayınlandı.
CoopCycle kullanıcıları şunları yapmalıdır:
- Yazılımın güncel bir sürümünü çalıştırdıklarını doğrulayın.
- Benzer koleksiyon düzeyinde boşluklar yaratabilecek tüm özel uzantıları veya eklentileri gözden geçirin.
- Tüm API rotaları genelinde okuma/yazma asimetrilerine odaklanarak güvenlik taramalarını yeniden çalıştırın.
Özet
Güvenliği deklaratif hale getiren frameworkler, geliştiricilerin yalnızca tekil nesneler için çalışan kalıplara güvenmesi durumunda tehlikeli boşlukları gizleyebilir. Basit bir kontrol—bir uç noktanın okuma tarafı, yazma tarafıyla aynı korumaya sahip mi?—aksi takdirde başarılı (yeşil) test setlerinin arkasında gizli kalacak olan bir cross-tenant veri sızıntısı türünü ortaya çıkarabilir.
