deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Supabase varsayılan yetkileri, RLS'nin erişemeyeceği şekilde anon'a 96 tabloda TRUNCATE verdi

Bir geliştirici, Supabase'ın varsayılan şema ACL'sinin anon'a 96 tabloda TRUNCATE yetkisi verdiğini bildiriyor — PostgreSQL satır düzeyinde güvenliğin (RLS) yönetemeyeceği bir yetki ve kendi migration'larına karşı yazılmış hiçbir denetleyicinin yakalayamayacağı bir durum.

Supabase varsayılan yetkileri, RLS'nin erişemeyeceği şekilde anon'a 96 tabloda TRUNCATE verdi

Ne oldu

Bir geliştirici, dev.to'da yayımladığı firsthand bir anlatımda, Supabase projesinin public şemasındaki 96 tabloda anon rolüne TRUNCATE yetkisi verdiğini, authenticated rolünün ise aynı yetkiye 109 tabloda sahip olduğunu fark ettiğini paylaştı. Yazara göre bu grant'ların tek birini bile kendisi yazmamış.

Keşif tesadüfi olmuş. Yazar, bir podcast özelliği geliştirirken, anonim ziyaretçilerin yayımlanmış yazıları okuyabildiğini doğrulamak amacıyla articles tablosunun yetkilerini kontrol etmiş. Bunun yerine, anon rolünün yetki listesinde INSERT, UPDATE, DELETE ve TRUNCATE'ı bulmuş.

Grant'lar nereden geldi

Gönderiye göre kaynak, Supabase'ın public şemasına uyguladığı varsayılan bir ACL. Bir default-privileges kaydı (pg_default_acl), o şemada oluşturulan her tablonun anon ve authenticated rollerine, kısaltması D (TRUNCATE için) ve t (TRIGGER için) içeren bir yetki setini otomatik olarak vermesine neden oluyor. Platform bu kararı, kullanıcı daha hiç SQL yazmadan önce vermiş; mevcut tablolardaki yetkileri geri almak ise tek başına yeterli değil, çünkü oluşturulacak bir sonraki tablo aynı varsayılanları devralıyor.

Satır düzeyinde güvenlik neden yardımcı olmuyor

Yazar, INSERT, UPDATE ve DELETE konusunda daha az endişeliydi: bu fiiller PostgreSQL satır düzeyinde güvenlik (RLS) kapsamında, projenin policy'leri fail-closed davranıyor ve anon'a ait hiçbir yazma policy'si yok. TRUNCATE ise farklı bir vaka. RLS yalnızca SELECT, INSERT, UPDATE ve DELETE'i kapsarken, TRUNCATE tek bir ifadede tablonun tamamını boşaltıyor ve yalnızca tablo düzeyindeki yetkilere tabi. TRIGGER da benzer davranıyor — yetkiyi tutan birisi trigger ekleyebiliyor; gönderi bunu, tablo sahibi olarak kod çalıştırmanın bir yolu olarak tanımlıyor.

Yazar önem derecesi konusunda da açık. Bu, yarın veritabanının silineceği bir senaryo değil: Supabase'ın API katmanı olan PostgREST, TRUNCATE fiilini ve trigger oluşturma endpoint'ini sunmuyor; dolayısıyla herkese açık bir anon anahtarı bu yetkileri API üzerinden kullanamıyor ve sömürmek için gerçek bir veritabanı bağlantısı gerekiyor. Asıl sorun, derinlemesine savunmanın (defence in depth) temeli — en kötü durumun RLS ile sınırlı olduğu varsayımı, RLS'nin yönetmediği iki fiil için çöküyor.

Her denetim neden yeşil kaldı

Yazar, bir yılı aşkın süredir yönetişim araçları geliştirmişti; bunlara, tablo oluşturan her migration'ın üç GRANT satırını da yazdığını doğrulamaktan tek işi olan bir pre-commit denetleyicisi de dahildi — öz test ve bir körlük sinyaliyle destekleniyordu. Denetleyici her seferinde yeşil raporladı — ve doğru söylüyordu. Migration dosyalarını metin olarak okuyor ve beklenen satırların varlığını doğruluyordu; tüm defekt, kimsenin yazmadığı grant'lardaydı. Beyan ettiklerinizi inceleyen bir araç, ilke olarak, hiç beyan etmediklerinizi fark etmenin bir yoluna sahip değil.

Düzeltme de aynı kör noktayı paylaştı

Aynı gün yazılan onarım migration'ı, public tabloları dolaşarak her iki rolden de TRUNCATE ve TRIGGER'ı geri aldı; geriye kalan grant'ları sayan ve sayı sıfır değilse rollback yapan bir öz doğrulama adımı içeriyordu. Sıfır raporladı. Ertesi gün, bağımsız bir sorgu, hâlâ TRUNCATE tutan yedi view buldu.

Sebep küçüktü: döngü yalnızca normal ve bölümlenmiş tabloları (relkind 'r' ve 'p') tarıyordu ve doğrulama sorgusu, yalnızca normal tabloları listeleyen bir sistem view'ı olan pg_tables'a join yapıyordu. Düzeltme ve doğrulaması aynı kör noktayı paylaşıyordu; bu yüzden doğrulama, düzeltmeyi asla yanlışlayamadı — oysa ikisi de gerçekten canlı veritabanını sorguluyordu.

Yazar bundan üç kural çıkarıyor: kapsamı hafızadan değil, bir catalog sorgusundan türetin; kabul sorgularını invariant ile tam olarak aynı genişlikte tutun, çünkü her ekstra predicate bir varsayımı kaçak olarak sokar; ve her "eksik" denetimini bir "fazla" denetimiyle eşleştirin — bir yıllık denetleyiciler eksik grant'lara karşı korudu, ama hiçbiri birinin fazla yetki tutup tutmadığını sormadı.

Yayımlanan düzeltme, tablolar, bölümlenmiş tablolar, view'lar ve materialized view'lar genelinde TRUNCATE ve TRIGGER'ı geri alıyor; varsayılan yetkileri (default privileges) değiştirerek yeni tabloların grant'ları yeniden büyütmesini engelliyor; ve kabul sorgusunu her deploy öncesinde çalışan zamanlanmış bir denetime dönüştürüyor. Yazar, pg_default_acl'nin genellikle iki kayıt tuttuğunu, birinin postgres diğerinin supabase_admin'e ait olduğunu belirtiyor; ikincisi permission denied nedeniyle değiştirilemiyor, ancak bu projede hiçbir kullanıcı nesnesine sahip değildi.

Neden önemli

Boşluk, düzinelerce yönetişim kuralına ve binlerce yeşil teste sahip bir projede bir yılı aşkın süre var oldu; ve yalnızca biri alakasız bir tabloya yan gözle bakınca ortaya çıktı. Yönetilen platformlar üzerine inşa yapan ekipler için ders şu: platform varsayılanları, sizin yazdığınız her şeyin ve araçlarınızın okuduğu her şeyin dışında durur. Supabase kullanıcıları, information_schema.role_table_grants sorgusunu anon ve authenticated rollerine verilmiş TRUNCATE ve TRIGGER grant'ları için sorgulayarak saniyeler içinde kendilerini denetleyebilir; sonuç boş değilse, bu grant'lar kendi SQL'lerinin ilk satırından daha eski demektir.

  • #supabase
  • #postgresql
  • #database-security
  • #row-level-security
  • #cloud

İlgili yazılar