Firebase Misconfiguration New Vector

What is Firebase?

First of all, a quick basic information about firebase.

Firebase is a platform by Google offering a suite of backend services for mobile and web app development. It includes features like real-time database, authentication, cloud messaging, hosting, and analytics. Developers use Firebase to streamline development, focusing more on user experiences than infrastructure management. It’s known for its ease of use, scalability, and ability to synchronize data in real time across clients.

One of the key advantages of Firebase is its ease of use and scalability. Developers can quickly integrate Firebase into their projects using its SDKs and APIs, and as their app grows, Firebase scales effortlessly to accommodate increasing user loads and data volumes.

Firebase Config And Detection

Detection of assets that run on Firebase Framework is pretty simple and straightforward. Wappalyzer extension can many times detect on its own, but you can also search for keywords like ‘firebase’ or ‘appspot’ and you will probably find a JS file (like firebase_init.js) or directly the Firebase config. Another option is to crawl through the site and search for google API key or the keywords discussed, as the configuration might be found in other JS files.

You may have seen on web/mobile applications, firebase needs the following information to initialize the SDK:

{

 apiKey: "YOUR_API_KEY",

 authDomain: "YOUR_AUTH_DOMAIN",

 projectId: "YOUR_PROJECT_ID",

 storageBucket: "YOUR_STORAGE_BUCKET",

 messagingSenderId: "YOUR_MESSAGING_SENDER_ID",

 databaseURL: "YOUR_DATABASE_URL",

 appId: "YOUR_APP_ID"

};

Those details are intended to be public. The usage is for the client to interact and authenticate with the Firebase services through Google’s API endpoints. But what could happen if there is poor configuration of the Firebase services?

Let’s start.

Bucket Storage Public Access

So the first thing that caught my eye was the storage bucket, so I started researching if a bucket can be publicly accessible like the ones on other cloud companies (AWS, GCP, Azure etc). The answer was YES, with a simple request, combining the API-Key (Sometimes, API-Key is also not needed) and the firebase storage bucket, you are able to list and read the entire bucket content with the following cURL request:

curl -k ‘https://firebasestorage.googleapis.com/v0/b/STORAGEBUCKET.appspot.com/o?maxResults=100’ -H ‘Authorization: Bearer <API_KEY>’

If the response status code is 200, you’ll be able to see the bucket listing. In order to read a file, you can use CURL or use an SDK like pyrebase4 (if you’re using python), here is the curl example:

curl -k ‘https://firebasestorage.googleapis.com/v0/b/STORAGEBUCKET.appspot.com/o/<URL-ENCODED-PATH>?alt=media’ -H ‘Authorization: Bearer <API_KEY>’

Write Permissions – Bucket

Most of the buckets I encountered were storing static files that are usually not sensitive information or helpful in pentesting. But what if the bucket also has public WRITE access? 

Buckets vulnerable to WRITE access can cause critical impact, such as stored XSS through JS/HTML/JSON that is imported from the bucket, site defacement, data loss or even RCE (Remote Code Execution).

Write access gives the permissions to also update or delete files.

You can achieve that with the following raw request:

We can see the file was uploaded by listing the bucket again, or accessing the file directly:

Misconfigured Database Access

Same as the storage bucket, a Firebase Realtime DB can be accessible with ANONYMOUS permissions, if misconfigured. This can lead to critical sensitive data exposure, like users, PII and other information. 

If the DB is also configured to allow WRITE permissions to anonymous users, the entire DB can be compromised by a malicious actor.

The misconfiguration can be exploited by simply adding ‘.json’ to the DB url, for example:

https://project-name.firebaseio.com/.json

Results:

You can try WRITE access by sending a POST request to an existing node or a new one if you would like to create it, by this example URL:

https://project-name.firebaseio.com/new-node.json

cURL request and response to write attempt:

Now when we list the Database content again:

To delete, just send a DELETE request to the created node’s URI.

User Registration

Firebase is also used to manage authentication with the web/mobile application that was developed. This is a comfortable feature for a developer, but configuring the permissions of the user is crucial.

First of all, think about private apps, like a mobile app for Android that is supposed to be accessible only by the employees of a company. The possibility of unauthenticated attacker to create a user and access the app’s features may itself impose risks to information confidentiality.

To register an account, you can send a POST request with the API Key to the following endpoints:

The only difference between the two endpoints is the API versions that is being used.

The request needs to be send with email, password and “returnSecureToken” parameter:

Another important thing is if you want to keep the registration enabled, make sure the user group’s permissions are configured correctly and not privileged enough to read/write your RealtimeDB or the Bucket.

Here is an example of a bucket writing attempts with and without a user:

Bucket writing forbidden:

Same bucket with user registration enabled, using the idToken to write:

Same can be done with the Database enumeration, by adding the query parameters ‘access_token=’ or ‘auth=’.

Remote Config Fetching

Firebase Remote Config is a feature provided by Google Firebase that allows developers to dynamically change the behavior and appearance of their apps without requiring users to download an app update.

Firebase Remote Config is primarily a backend service provided by Firebase. However, its integration typically involves both backend and frontend components. The backend component involves configuring and managing the Remote Config settings through the Firebase console or API.

This feature can be accessible (if allowed by the configuration) with the API key and few other parameters, and the response may contain sensitive information that was left there by the developer:

Our Remediation Plan

  • Realtime DB and Storage Bucket: Immediately revoke any access for anonymous users. This can be accomplished by setting the read and write permissions in the configuration to "False".
  • API Key Permissions: Ensure that the API key distributed to client-side does not grant excessive permissions, particularly for read and write operations. Review and restrict API key permissions rigorously.
  • Remote Config Fetching: Remove permissions associated with the API key for this feature. If maintaining this feature client-side is necessary, ensure that it does not disclose any sensitive information.
  • User Registration: Restrict read/write permissions for accounts newly created through the user registration feature. Manage this effectively by assigning new users to groups with limited permissions by default. This step is crucial to prevent newly created users from performing unrestricted queries against the database and storage bucket, thereby circumventing the limitations imposed on anonymous users.
  • Private Application Security: For applications intended to remain private, either revoke registration capabilities from the shared API key or disable registration features altogether to safeguard against unauthorized access.