Unsichere Regeln vermeiden

In diesem Leitfaden finden Sie Informationen zu häufigen Sicherheitslücken in Konfigurationen von Firebase Security Rules. Sie erfahren, wie Sie Ihre eigenen Regeln prüfen, deren Sicherheit erhöhen und Änderungen vor der Bereitstellung testen können.

Wenn Sie eine Warnung erhalten, dass Ihre Daten nicht ordnungsgemäß geschützt sind, sehen Sie sich diese häufigen Fehler an und aktualisieren Sie alle anfälligen Regeln.

Auf Firebase Security Rules zugreifen

Sie können Ihre vorhandenen Rules entweder mit der Firebase CLI oder der Firebase Console aufrufen. Bearbeiten Sie Ihre Regeln immer mit derselben Methode, um zu vermeiden, dass Aktualisierungen versehentlich überschrieben werden. Wenn Sie nicht sicher sind, ob Ihre lokal definierten Regeln die neuesten Updates widerspiegeln, wird in der Firebase Console immer die zuletzt bereitgestellte Version Ihrer Firebase Security Rules angezeigt.

Wenn Sie über die Firebase-Konsole auf Ihre Regeln zugreifen möchten, wählen Sie Ihr Projekt aus und gehen Sie dann zu Realtime Database, Cloud Firestore oder Speicher. Klicken Sie auf Regeln, sobald Sie sich in der richtigen Datenbank oder dem richtigen Speicher-Bucket befinden.

Wenn Sie über die Firebase-CLI auf Ihre Regeln zugreifen möchten, rufen Sie die Regeldatei auf, die in der firebase.json-Datei vermerkt ist.

Firebase Security Rules

Firebase Security Rules schützen Ihre Daten vor böswilligen Nutzern. Wenn Sie eine Datenbankinstanz oder einen Cloud Storage-Bucket in der Firebase Console erstellen, können Sie entweder allen Nutzern den Zugriff verweigern (Gesperrter Modus) oder allen Nutzern Zugriff gewähren (Testmodus). Auch wenn Sie während der Entwicklung eine offenere Konfiguration wünschen, sollten Sie sich die Zeit nehmen, Ihre Regeln richtig zu konfigurieren und Ihre Daten zu schützen, bevor Sie Ihre App bereitstellen.

Wenn Sie Ihre Anwendung entwickeln und verschiedene Konfigurationen für Ihre Regeln testen möchten, können Sie die Anwendung mit einem der lokalen Firebase-Emulatoren in einer lokalen Entwicklungsumgebung ausführen.

Häufige Szenarien mit unsicheren Regeln

Die Rules, die Sie möglicherweise standardmäßig übernommen oder zu Beginn der Entwicklung Ihrer Anwendung eingerichtet haben, sollten vor der Bereitstellung der Anwendung geprüft und aktualisiert werden. Achten Sie darauf, dass Sie die Daten Ihrer Nutzer sicher schützen, indem Sie die folgenden häufigen Schwierigkeiten vermeiden.

Unbeschränkter Zugriff

Bei der Einrichtung Ihres Firebase-Projekts haben Sie möglicherweise Ihre Regeln so festgelegt, dass für die Entwicklung ein offener Zugriff möglich ist. Eventuell gehen Sie auch davon aus, dass Sie die einzige Person sind, die Ihre Anwendung nutzt. Allerdings ist sie nach dem Bereitstellen im Internet verfügbar. Wenn Sie Nutzer nicht authentifizieren und keine Sicherheitsregeln konfigurieren, kann jeder, der Ihre Projekt-ID errät, die Daten stehlen, ändern oder löschen.

Nicht empfohlen:Lese- und Schreibzugriff für alle Nutzer.
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this ruleset in production; it allows
// anyone to overwrite your entire database.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}
{
  // Allow read/write access to all users under any conditions
  // Warning: **NEVER** use this ruleset in production; it allows
  // anyone to overwrite your entire database.

  "rules": {
    ".read": true,
    ".write": true
  }
}
    
// Anyone can read or write to the bucket, even non-users of your app.
// Because it is shared with App Engine, this will also make
// files uploaded using App Engine public.
// Warning: This rule makes every file in your Cloud Storage bucket accessible to any user.
// Apply caution before using it in production, since it means anyone
// can overwrite all your files.

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}
    
Lösung: Legen Sie Regeln fest, die den Lese- und Schreibzugriff beschränken.

Erstellen Sie Regeln, die für Ihre Datenhierarchie sinnvoll sind. Eine der gängigsten Lösungen für diese unsichere Konfiguration ist die nutzerbasierte Sicherheit mit Firebase Authentication. Weitere Informationen dazu finden Sie unter Nutzer mit Regeln authentifizieren.

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{document} {
      // Allow reads and deletion if the current user owns the existing document
      allow read, delete: if request.auth.uid == resource.data.author_uid;
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;

    }
  }
}
  
service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}
  
{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}
    
{
  // Allow anyone to read data, but only authenticated content owners can
  // make changes to their data

  "rules": {
    "some_path/$uid": {
      ".read": true,
      // or ".read": "auth.uid !== null" for only authenticated users
      ".write": "auth.uid === $uid"
    }
  }
}
    
// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}
  

Zugriff für jeden authentifizierten Nutzer

Manchmal prüfen Rules-Regeln, ob ein Nutzer angemeldet ist, schränken den Zugriff aber nicht weiter ein. Wenn eine Ihrer Regeln auth != null enthält, haben alle angemeldeten Nutzer Zugriff auf die Daten.

Nicht empfohlen:Jeder angemeldete Nutzer hat Lese- und Schreibzugriff auf Ihre gesamte Datenbank.
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth.uid != null;
    }
  }
}
{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}
// Only authenticated users can read or write to the bucket
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
Lösung: Grenzen Sie den Zugriff mithilfe von Sicherheitsbedingungen ein.

Wenn Sie die Authentifizierung prüfen lassen, können Sie auch eines der Authentifizierungsattribute verwenden, um den Zugriff für bestimmte Nutzer und bestimmte Datensätze weiter einzuschränken. Weitere Informationen zu den verschiedenen Authentifizierungseigenschaften

service cloud.firestore {
  match /databases/{database}/documents {
    // Assign roles to all users and refine access based on user roles
    match /some_collection/{document} {
     allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"

     // Note: Checking for roles in your database using `get` (as in the code
     // above) or `exists` carry standard charges for read operations.
    }
  }
}
// Give each user in your database a particular attribute
// and set it to true/false
// Then, use that attribute to grant access to subsets of data
// For example, an "administrator" attribute set
// to "true" grants write access to data

service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
      allow read: true;
    }
  }
}
  
service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      allow read: if true
      allow write: if request.auth.uid == request.resource.data.author_uid
    }
  }
}
  
{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth.uid === $uid",
        ".write": "auth.uid === $uid"
      }
    }
  }
}
    
{
  "rules": {
    "some_path/$uid": {
      ".write": "auth.uid === $uid",
      // Create a "public" subpath in your dataset
      "public": {
        ".read": true
        // or ".read": "auth.uid !== null"
      },
      // Create a "private" subpath in your dataset
      "private": {
        ".read": "auth.uid === $uid"
      }
    }
  }
}
    
{
  // Allow anyone to read data, but only authenticated content owners can
  // make changes to their data

  "rules": {
    "some_path/$uid": {
      ".read": true,
      // or ".read": "auth.uid !== null" for only authenticated users
      ".write": "auth.uid === $uid"
    }
  }
}
    
// Allow reads if the group ID in your token matches the file metadata `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}
// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}
  

(Realtime Database) Falsch übernommene Regeln

Realtime Database Security Rules kaskadieren, wobei Regeln in flacheren übergeordneten Pfaden Regeln in tieferen untergeordneten Knoten überschreiben. Wenn Sie eine Regel für einen untergeordneten Knoten schreiben, denken Sie daran, dass damit nur zusätzliche Berechtigungen gewährt werden können. Sie können den Zugriff auf Daten in einem tieferen Pfad in Ihrer Datenbank nicht einschränken oder widerrufen.

Nicht empfohlen:Regeln für untergeordnete Pfade verfeinern
{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}
Lösung:Erstellen Sie allgemeine Regeln für übergeordnete Pfade und gewähren Sie spezifischere Berechtigungen für untergeordnete Pfade. Wenn Ihre Anforderungen an den Datenzugriff detaillierter sind, sollten Sie Ihre Regeln entsprechend formulieren. Weitere Informationen zur Kaskadenerstellung von Realtime Database Security Rules finden Sie in der Grundlegenden Syntax von Realtime Database Security Rules.

Geschlossener Zugriff

Ein weiterer gängiger Ansatz während der Entwicklung Ihrer Anwendung besteht darin, Ihre Daten zu sperren. In der Regel bedeutet dies, dass Sie den Lese- und Schreibzugriff für alle Nutzer folgendermaßen gesperrt haben:

// Deny read/write access to all users under any conditions
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}
{
  "rules": {
    ".read": false,
    ".write": false
  }
}
    
// Access to files through Cloud Storage is completely disallowed.
// Files may still be accessible through App Engine or Google Cloud Storage APIs.

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

Die Firebase Admin SDKs und Cloud Functions haben aber weiterhin Zugriff auf Ihre Datenbank. Verwenden Sie diese Regeln, wenn Sie Cloud Firestore oder Realtime Database zusammen mit dem Firebase Admin SDK als reines Server-Back-End verwenden möchten. Dies ist zwar sicher, Sie müssen aber testen, ob die Clients Ihrer Anwendung Daten ordnungsgemäß abrufen können.

Weitere Informationen zu Cloud Firestore Security Rules und ihrer Funktionsweise finden Sie unter Erste Schritte mit Cloud Firestore Security Rules.

Cloud Firestore Security Rules testen

Verwenden Sie den Firebase-Emulator, um das Verhalten Ihrer Anwendung und die Konfigurationen Ihrer Cloud Firestore Security Rules zu prüfen. Verwenden Sie den Cloud Firestore-Emulator, um Einheitentests in einer lokalen Umgebung auszuführen und zu automatisieren, bevor Sie Änderungen bereitstellen.

Wenn Sie Firebase Security Rules schnell in der Firebase Console validieren möchten, verwenden Sie den Firebase-Regeln-Simulator.