← Poradniki stacków

Firebase

Bezpieczeństwo dla twojej aplikacji z Firebase

Bezpieczeństwo Firebase zależy prawie całkowicie od reguł, które napiszesz. Z regułami w trybie testowym albo zbyt otwartymi twoja baza danych jest w zasięgu każdego. Sprawdź to, zanim otworzysz aplikację.

Typowe ryzyka przy Firebase

Reguły w trybie testowym

Tryb testowy pozwala każdemu na odczyt i zapis. Wielu ludzi uruchamia aplikację bez jego zmiany, zostawiając bazę danych całkowicie otwartą.

Mylenie klucza publicznego z zabezpieczeniem

Konfiguracja Firebase jest publiczna z założenia; to reguły chronią twoje dane, a nie ukrywanie tego klucza. Zakładanie inaczej prowadzi do ujawnienia danych.

Inne klucze we frontendzie

Obok konfiguracji Firebase często wkradają się klucze, które naprawdę są tajne (płatności, email, AI). Te nigdy nie mogą znaleźć się w JavaScripcie przeglądarki.

„Bezpieczeństwo Firebase" to dwie rzeczy, które warto rozdzielić. Pierwsza to model Firebase: przeglądarka rozmawia bezpośrednio z bazą danych i magazynem plików, więc nie ma serwera, który filtruje, a ochrona żyje w regułach, w App Check i w konfiguracji projektu. Druga to to, co Lovable, Bolt czy Cursor robią z Firebase przy generowaniu kodu, i stamtąd biorą się niemal wszystkie dziury. Ten przewodnik wyjaśnia model, omawia, co AI robi źle, zostawia Ci firebase.json i bazowe reguły do wklejenia, prompt do przeglądu i kontrolę z zewnątrz. Dziesięć najczęstszych błędów w regułach, ze złą i dobrą regułą, jest w najczęstsze błędy bezpieczeństwa w Firebase.

Część 1: jak działa bezpieczeństwo w Firebase

Klient rozmawia z usługami, nie z Twoim serwerem

W typowej aplikacji Firebase nie ma własnego backendu: SDK w przeglądarce czyta i zapisuje bezpośrednio do Firestore, Realtime Database i Storage. To oznacza, że obiekt konfiguracji z apiKey i projectId jest publiczny z założenia (identyfikuje projekt, niczego nie autoryzuje), a jedyną barierą między odwiedzającym a Twoimi danymi są reguły bezpieczeństwa. Każdy produkt ma własne: Firestore, Realtime Database i Storage konfiguruje się osobno, a w aplikacji zwykle otwarte jest to, na co nikt nie spojrzał.

Reguły odpowiadają na pytanie „kto może co"

Reguła dostaje żądanie z uwierzytelnionym użytkownikiem (request.auth), dokument, który ma być odczytany lub zapisany, i nowe dane (request.resource.data). Na tej podstawie decyduje. Kluczowe rozróżnienie to uwierzytelniony (jest sesja) kontra autoryzowany (ta sesja może widzieć ten dokument): request.auth != null sprawdza tylko pierwsze, a rejestracja jest darmowa. Reguły walidują też, co jest zapisywane, żeby użytkownik nie ustawił sobie isAdmin: true we własnym profilu.

Co chroni oprócz reguł

  • App Check. Wymaga, żeby żądania pochodziły z Twojej prawdziwej aplikacji (przez reCAPTCHA lub Play Integrity), a nie ze skryptu z Twoim projectId. Hamuje nadużycia i nieoczekiwane rachunki za masowe odczyty.
  • Ograniczenie klucza API. W konsoli Google Cloud ogranicz klucz do domen Twojej strony i do API, których używasz. Nie zastępuje reguł, ale zamyka jedne drzwi.
  • Auth. Autoryzowane domeny logowania, ochrona przed enumeracją e-maili, weryfikacja e-maila, tylko te metody logowania, których naprawdę używasz, uwierzytelnianie wieloskładnikowe, jeśli przetwarzasz wrażliwe dane.
  • Cloud Functions jako serwer. Wszystko, co potrzebuje sekretnego klucza (płatności, e-mail, AI), idzie do funkcji, z sekretem w Secret Manager, a klient wywołuje funkcję. Uwaga: funkcja HTTP jest publiczna dla całego internetu, chyba że sprawdzasz token użytkownika albo używasz funkcji callable z App Check.
  • Budżet. Firebase liczy za odczyt i za wywołanie. Alerty budżetowe w Google Cloud i limity w regułach (request.query.limit) zapobiegają temu, żeby pętla albo atakujący zostawili Ci rachunek.

Hosting: co Firebase ustawia, a czego nie

Firebase Hosting daje automatyczny TLS, CDN i przekierowanie na HTTPS. Nie ustawia nagłówków bezpieczeństwa: dodaje się je w firebase.json. I serwuje wszystko, co jest w katalogu publicznym, łącznie z .env skopiowanym przez pomyłkę.

Część 2: co AI robi źle z Firebase

  • Reguły w trybie testowym, a potem if true. AI zostawia reguły otwierające wszystko na trzydzieści dni; po wygaśnięciu aplikacja pada, a szybkie rozwiązanie to otworzyć je na stałe.
  • request.auth != null jako jedyny warunek. Każdy zarejestrowany użytkownik czyta dane wszystkich innych.
  • Zapisy bez walidacji. Profil ma role albo credits, a reguła update nie wyklucza tych pól.
  • Inne klucze w bundle'u. Obok konfiguracji Firebase pojawia się sekretny klucz Stripe, klucz OpenAI albo klucz usługi mailowej. Szczegóły w sekrety, które Twoja aplikacja wycieka w przeglądarce.
  • Funkcje HTTP niesprawdzające użytkownika. Funkcja, która pobiera opłaty, wysyła e-maile albo wywołuje model, odpowiada każdemu, kto zna URL.
  • Storage z regułami skopiowanymi z Firestore. allow read, write: if request.auth != null w storage.rules: każdy użytkownik czyta pliki innych i wgrywa, co chce.
  • Bez App Check, bez nagłówków, bez alertów. Trzy pola, których nikt nie zaznacza, bo aplikacja „już działa".

Blok do wklejenia w projekt

Nagłówki bezpieczeństwa w firebase.json (Content-Security-Policy idzie osobno, bo zależy od Twoich skryptów):

{
  "hosting": {
    "public": "dist",
    "headers": [
      {
        "source": "**",
        "headers": [
          { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
          { "key": "X-Content-Type-Options", "value": "nosniff" },
          { "key": "X-Frame-Options", "value": "DENY" },
          { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
          { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
        ]
      }
    ]
  }
}

I punkt wyjścia dla firestore.rules: domyślnie wszystko zamknięte, każdy użytkownik swój dokument, pola uprawnień chronione.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null && request.auth.uid == userId
        && !request.resource.data.keys().hasAny(['role', 'isAdmin', 'plan', 'credits']);
      allow update: if request.auth != null && request.auth.uid == userId
        && !request.resource.data.diff(resource.data).affectedKeys()
           .hasAny(['role', 'isAdmin', 'plan', 'credits']);
    }
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Dodaj potem jawną regułę dla każdej kolekcji; ostatnia, z if false, gwarantuje, że każda nowa kolekcja rodzi się zamknięta.

Prompt do przeglądu przed publikacją

Przejrzyj bezpieczeństwo tej aplikacji z Firebase i na razie niczego nie zmieniaj. Odpowiedz listą:
1. Reguły Firestore, Realtime Database i Storage, które dają dostęp każdemu, z datą trybu testowego albo z request.auth != null jako jedynym warunkiem.
2. Reguły zapisu, które nie walidują pól, zwłaszcza role, isAdmin, plan lub credits.
3. Klucze inne niż konfiguracja Firebase obecne w kodzie przeglądarki, z plikiem i linią.
4. Cloud Functions HTTP, które nie weryfikują tokena użytkownika, oraz funkcje czytające sekrety z kodu zamiast z Secret Manager.
5. Czy App Check jest włączony i czy klucz API jest ograniczony do domen.
6. Nagłówki bezpieczeństwa w firebase.json i pliki w katalogu publicznym, których nie powinno tam być.
Dla każdego punktu zaproponuj dokładną regułę lub zmianę i poczekaj na moje potwierdzenie.

Sprawdź wynik z zewnątrz

Twoje projectId jest w bundle'u, więc każdy może to zrobić. REST API Firestore bez tokena:

curl -s "https://firestore.googleapis.com/v1/projects/TWOJ_PROJEKT/databases/(default)/documents/users" | head -c 400
curl -sI https://twojadomena.com | grep -iE "strict-transport|x-frame|x-content-type"

Prawidłowy wynik to błąd uprawnień w pierwszym (jeśli zwraca dokumenty, kolekcja jest otwarta) i nagłówki w drugim. Powtórz pierwsze dla każdej kolekcji i dla Storage. Scanaris wykonuje te kontrole i około czterdziestu innych w 30 sekund: wykrywa konfigurację Firebase w Twoim bundle'u, odpytuje typowe kolekcje bez uwierzytelnienia, szuka innych kluczy w JavaScripcie, sprawdza nagłówki, CORS, ciasteczka i wystawione pliki, a dla każdego znaleziska daje fix prompt do wklejenia w Lovable, Bolt lub Cursor. Jeśli Twoja aplikacja używa Supabase zamiast Firebase, odpowiednikiem jest przewodnik po Supabase.

Często zadawane pytania

Czy muszę ukrywać apiKey Firebase?

Nie. Jest publiczny z założenia i identyfikuje projekt. Dane chronią reguły i App Check. Warto za to ograniczyć go do Twoich domen w Google Cloud.

Czy Cloud Functions są prywatne?

Funkcja HTTP to publiczny URL. Sprawdzaj token użytkownika wewnątrz funkcji albo używaj funkcji callable z App Check. Funkcje reagujące na zdarzenia (utworzony dokument, wgrany plik) nie mają URL-a i faktycznie są wewnętrzne.

Jak przetestować reguły bez psucia aplikacji?

Symulatorem w konsoli (zakładka Reguły) do testowania konkretnych odczytów i lokalnym emulatorem do testów automatycznych. Zmieniaj reguły z aplikacją otwartą w drugiej karcie i sprawdzaj, czy to, co ma działać, nadal działa.

Powiązane testy

Czy twoja aplikacja Firebase przechodzi te testy?

Przeskanuj ją za darmo i otrzymaj prompt naprawczy dla każdego znalezionego problemu.

Przeskanuj moją stronę za darmo