● CWE-862 · OWASP A01:2021

Supabase और Firebase के access नियम (CWE-862): Row Level Security न होने से डेटा कैसे उजागर होता है और इसे कैसे ठीक करें

Supabase और Firebase ऐप्स browser को एक सार्वजनिक key से सीधे database query करने देते हैं, इसलिए किसी विज़िटर और हर row के बीच केवल Row Level Security या Security Rules होते हैं। enable row level security के बिना SQL से बनी table, या allow read, write: if true पर छोड़ा गया Firestore नियम, कोई भी पढ़ और बदल सकता है। USING और WITH CHECK policies rows को लॉग-इन यूज़र तक कैसे सीमित करती हैं, PostgreSQL migration के उदाहरण के साथ।

आसान भाषा में (ELI5)

एक दफ़्तरी इमारत हर विज़िटर को एक ही लॉबी कार्ड देती है, जो ब्रोशर के पीछे छपा है। जब तक हर मंज़िल का दरवाज़ा खुलने से पहले आपकी पहचान जाँचता है, तब तक यह ठीक है। एक मंज़िल जल्दबाज़ी में तैयार हुई और उसके दरवाज़े पर कोई reader ही नहीं है, इसलिए लॉबी कार्ड से वह खुल जाता है और कोई भी अंदर जाकर फ़ाइलें पढ़ सकता है। Supabase की anon key वही लॉबी कार्ड है: इसे सार्वजनिक ही होना है। Row Level Security हर मंज़िल के दरवाज़े का reader है। उपाय है हर दरवाज़े पर reader लगाना और उसे सटीक बताना कि कौन किसकी फ़ाइलें देख सकता है।

इस पेज के मुख्य शब्द

सार्वजनिक anon key
Supabase की anon key और Firebase की web config ऐप bundle के अंदर जाती हैं, और कोई भी उन्हें कॉपी कर सकता है। ये project की पहचान करती हैं, यूज़र की नहीं, इसलिए ये गुप्त नहीं हैं और अकेले डेटा की रक्षा नहीं कर सकतीं।
Row Level Security (RLS)
PostgreSQL की एक सुविधा जो हर query को policies से छानती है। Supabase का Table Editor नई tables पर इसे चालू करता है, पर SQL या migrations से बनी tables RLS बंद होने के साथ शुरू होती हैं, और डिफ़ॉल्ट अनुमतियाँ तब anon और authenticated को हर row पढ़ने और बदलने देती हैं।
USING और WITH CHECK
USING तय करता है कि यूज़र कौन-सी मौजूदा rows देख, बदल या मिटा सकता है; WITH CHECK तय करता है कि वह कौन-सी नई या बदली हुई rows लिख सकता है। insert या update पर केवल USING वाली policy यूज़र्स को दूसरे संगठन के लिए rows लिखने देती है।
service_role key
service_role key RLS को पूरी तरह बायपास करती है। इसकी जगह केवल सर्वर और edge functions में है, कभी browser या mobile ऐप में नहीं।
Firestore के test-mode नियम
test mode में शुरू किए projects को ऐसे नियम मिलते हैं जो किसी तारीख़ तक सारी reads और writes की अनुमति देते हैं, और कई बाद में allow read, write: if true में बदल दिए जाते हैं। नियमों को request.auth.uid की तुलना document के owner field से करनी चाहिए।

हमले का चरण-दर-चरण प्रवाह

चरण 1

हमलावर ऐप खोलता है

Supabase URL और anon key JavaScript bundle या mobile ऐप package में होती हैं।

चरण 2

वह सीधे table को query करता है

वह ऐप की स्क्रीनों को छोड़कर केवल anon key के साथ invoices के REST endpoint को बुलाता है। anon key और बिना यूज़र session के टेस्ट project को भेजी गई रिक्वेस्ट यह मामला दिखाती है।

चरण 3

database हर row लौटा देता है

RLS बंद है और anon के पास select अधिकार है, इसलिए PostgreSQL कोई फ़िल्टर नहीं लगाता और सभी संगठनों के invoices लौटा देता है।

चरण 4

डेटा लीक होता या बदलता है

अगर update और delete भी दिए हों, तो हमलावर records बदल या मिटा सकता है। 2025 में CVE-2025-48757 जारी हुआ, जब शोधकर्ताओं ने पाया कि एक AI app builder से बने 170 से ज़्यादा ऐप्स में RLS न होने से डेटा उजागर था।

सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन

कमज़ोर कार्यान्वयन
-- migration.sql: इस table पर RLS कभी चालू नहीं होता
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
);

-- सार्वजनिक anon key हर row पढ़, बदल और मिटा सकती है
grant select, insert, update, delete on public.invoices to anon, authenticated;
सुरक्षित और सुदृढ़ फ़िक्स
-- migration.sql: RLS चालू, anon से अधिकार वापस, हर command की एक policy
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
);

-- RLS चालू होने पर बिना policy के कोई access नहीं
alter table public.invoices enable row level security;
revoke all on public.invoices from anon;

-- यूज़र केवल अपने संगठनों के invoices देखते हैं
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())));

-- नई rows यूज़र के किसी संगठन की होनी चाहिए; update या delete policy नहीं
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())));

इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट

स्रोत

← पूरी सुरक्षा निर्देशिका देखें सभी कमज़ोरी गाइड →