● CWE-862 · OWASP A01:2021

Aturan akses Supabase dan Firebase (CWE-862): bagaimana Row Level Security yang hilang mengekspos data dan cara memperbaikinya

Aplikasi Supabase dan Firebase membiarkan browser mengkueri database secara langsung dengan kunci publik, sehingga satu-satunya penghalang antara pengunjung dan setiap baris adalah Row Level Security atau Security Rules. Tabel yang dibuat lewat SQL tanpa enable row level security, atau aturan Firestore yang dibiarkan allow read, write: if true, bisa dibaca dan diubah siapa saja. Bagaimana kebijakan USING dan WITH CHECK membatasi baris ke pengguna yang sedang login, dengan contoh migrasi PostgreSQL.

Penjelasan Sederhana (ELI5)

Sebuah gedung kantor memberi setiap tamu kartu lobi yang sama, dicetak di balik brosur. Itu tidak masalah selama pintu setiap lantai memeriksa siapa Anda sebelum terbuka. Satu lantai disiapkan terburu-buru dan pintunya tidak punya pembaca kartu sama sekali, sehingga kartu lobi bisa membukanya dan siapa pun bisa masuk membaca berkas. Kunci anon Supabase adalah kartu lobi itu: memang dimaksudkan publik. Row Level Security adalah pembaca kartu di pintu setiap lantai. Perbaikannya adalah memasang pembaca di setiap pintu dan memberitahunya dengan tepat berkas siapa yang boleh dilihat tiap orang.

Konsep Kunci & Istilah

Kunci anon publik
Kunci anon Supabase dan konfigurasi web Firebase ikut di dalam bundle aplikasi, dan siapa pun bisa menyalinnya. Keduanya mengidentifikasi proyek, bukan pengguna, jadi bukan rahasia dan tidak bisa melindungi data sendirian.
Row Level Security (RLS)
Fitur PostgreSQL yang menyaring setiap kueri melalui kebijakan. Table Editor Supabase mengaktifkannya untuk tabel baru, tetapi tabel yang dibuat lewat SQL atau migrasi dimulai dengan RLS mati, dan hak akses default lalu membiarkan anon dan authenticated membaca dan mengubah setiap baris.
USING dan WITH CHECK
USING menentukan baris yang sudah ada mana yang boleh dilihat, diubah, atau dihapus pengguna; WITH CHECK menentukan baris baru atau yang diubah mana yang boleh ia tulis. Kebijakan yang hanya punya USING pada insert atau update membiarkan pengguna menulis baris untuk organisasi lain.
Kunci service_role
Kunci service_role melewati RLS sepenuhnya. Tempatnya hanya di server dan edge function, tidak pernah di browser atau aplikasi seluler.
Aturan Firestore mode uji
Proyek yang dimulai dalam mode uji mendapat aturan yang mengizinkan semua baca dan tulis hingga tanggal tertentu, dan banyak yang kemudian diubah menjadi allow read, write: if true. Aturan harus mencocokkan request.auth.uid dengan field pemilik dokumen.

Alur Serangan Langkah demi Langkah

Langkah 1

Penyerang membuka aplikasi

URL Supabase dan kunci anon ada di bundle JavaScript atau paket aplikasi seluler.

Langkah 2

Ia mengkueri tabel secara langsung

Ia memanggil endpoint REST untuk invoices hanya dengan kunci anon, melewati layar aplikasi. Request ke proyek uji dengan kunci anon dan tanpa sesi pengguna menggambarkan kasus ini.

Langkah 3

Database mengembalikan setiap baris

RLS mati dan anon punya hak select, sehingga PostgreSQL tidak menyaring apa pun dan mengembalikan invoice semua organisasi.

Langkah 4

Data bocor atau diubah

Jika update dan delete juga diberikan, penyerang bisa mengubah atau menghapus record. CVE-2025-48757 diterbitkan pada 2025 setelah peneliti menemukan RLS yang hilang mengekspos data di lebih dari 170 aplikasi yang dibuat oleh satu pembuat aplikasi berbasis AI.

Kode Sumber: Rentan vs Aman

IMPLEMENTASI RENTAN
-- migration.sql: RLS tidak pernah diaktifkan di tabel ini
create table public.invoices (
  id bigint generated always as identity primary key,
  org_id uuid not null references public.orgs (id),
  customer text not null,
  amount_cents bigint not null
);

-- kunci anon publik bisa membaca, mengubah, dan menghapus setiap baris
grant select, insert, update, delete on public.invoices to anon, authenticated;
PERBAIKAN AMAN & KUAT
-- migration.sql: RLS aktif, hak anon dicabut, satu kebijakan per perintah
create table public.invoices (
  id bigint generated always as identity primary key,
  org_id uuid not null references public.orgs (id),
  customer text not null,
  amount_cents bigint not null
);

-- setelah RLS aktif, tanpa kebijakan berarti tanpa akses
alter table public.invoices enable row level security;
revoke all on public.invoices from anon;

-- pengguna hanya melihat invoice organisasi tempat mereka bergabung
create policy "members read their org's invoices"
  on public.invoices for select to authenticated
  using (org_id in (select org_id from public.memberships where user_id = (select auth.uid())));

-- baris baru harus milik salah satu organisasi pengguna; tidak ada kebijakan update atau delete
create policy "members add invoices to their org"
  on public.invoices for insert to authenticated
  with check (org_id in (select org_id from public.memberships where user_id = (select auth.uid())));

Daftar Periksa Penguatan Sistem Rekayasa

Sumber

← Lihat seluruh direktori keamanan Semua panduan kerentanan →