Search code examples
firebasefirebase-realtime-databasefirebase-security

Securing Google Firebase from DDOS / attackers and prevent surprise bills


Im thinking of using firebase real time database but there are a few things im afraid of:

  • High surprise bills
  • System failure

There are a few things im thinking of doing:

  • Layer 1: CloudFare CDN in front of Firebase.
  • Layer 2: Security rules with time based rate limiting on write / read operations.
  • Layer 3: Only well authentificated users can call firebase endpoints.
  • Emergency Layer: I track the amount of read and write operations. If these are over a certain threshhold, I disabled billing on my project.

Is this secure enough?

How can I secure my firebase from read / write exploits or ddos?


Solution

  • You general approach around the three steps is good practice.

    Please consider Firebase is cloud based so its exposure is front and center to the world, here are some specific recommendations to firebase and how to introduce watch dog practises:

    Avoid insecure rules

    // 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;
        }
      }
    
    
    }
    

    Look out for rule cascading , make sure you traverse the entire tree to check rules

    {
        "rules": {
            "users": {
                "$uid": {
                    ".read": "auth.uid == $uid || root.child('users').child(auth.uid).child('isAdmin').val() == true",
                    ".write": "root.child('users').child(auth.uid).child('isAdmin').val() == true",
                    ".indexOn": ["email"]
                }
            }
        }
    }
    

    Like the code below, since authorization on create allows malicious users created (perhaps by bots)

    IMHO - I would make this manual or atleast have it checked against the users registration IP against something like honeypot

    const getCustomClaimsByEmail = require('../utilities/get-custom-claims-by-email');
    const setCustomClaims = require('../utilities/set-custom-claims');
    
    module.exports = ({ admin, environment }) => user => {
      const db = admin.firestore();
      const usersCollection = db.collection(environment.schema.users);
      const customClaimsRef = admin.database().ref(environment.schema.customClaims);
      const auth = admin.auth();
      const email = extractEmailFromUser(user);
    
      return Promise.resolve()
        .then(getCustomClaimsByEmail(customClaimsRef, email))
        .then(setCustomClaims(auth, user.uid))
        .then(claims => {
          const update = mapUserUpdate(claims, user);
          return usersCollection.doc(user.uid).set(update, { merge: true });
        });
    };
    
    function mapUserUpdate(claims, user) {
      const email = extractEmailFromUser(user);
    
      return {
        claims,
        email,
        emailVerified: user.emailVerified,
        lastSignInTime: user.metadata.lastSignInTime,
        creationTime: user.metadata.creationTime,
        providerData: user.providerData,
      };
    }
    
    function extractEmailFromUser(user) {
      return user.email || user.providerData.find(({ email }) => email).email;
    }
    

    Now to your DDOS / traffic,

    you can avoid abusive traffic by following this checklist, and during launch follow these checklist.