Firebase Security Vulnerability: FBR-PERF-002¶
Name: Lack of Rate Limiting on Write Operations
Applicable Services: Cloud Firestore, Firebase Realtime Database, Cloud Storage
Description¶
Note
This performance and cost vulnerability occurs when security rules fail to enforce a limit on how frequently a user can perform write operations.
- The Technical Flaw: The security rule for a
create
orupdate
operation only validates authentication or basic data, but it lacks a time-based condition to check how recently the user last performed a similar action. - Intended Behavior: Critical or expensive operations should be rate-limited. A user should only be able to perform a certain number of actions within a given time window to prevent abuse, whether intentional or accidental.
- The Risk: An unconstrained write operation can be exploited to drive up operational costs significantly. An attacker can write a simple script to create thousands of documents per minute, with each
create
operation adding to your Firebase bill. This can also lead to performance degradation for other users.
Impact¶
Potential Consequences
The severity of this vulnerability is a warning. Exploiting it can lead to: * Excessive Costs: The primary impact is financial. Automated scripts can generate thousands or millions of write operations, leading to a surprisingly large bill. * Denial of Service (DoS): While less common, extremely high-frequency writes to a specific part of your database can create a "hotspot," degrading read and write performance for legitimate users and potentially making the application unresponsive. * Data Spam: The database can be flooded with useless or malicious data, making moderation difficult and degrading the user experience.
Example Attack Scenarios¶
Exploit Scenario: Spamming a Collection with Unrestricted Writes
- The Vulnerable Rule: The following Firestore rule allows any authenticated user to create a document in the
user_feedback
collection. There is no limit on how often they can do this. - Attacker's Goal: To inflict financial damage by creating a massive number of documents.
- The Exploit: The attacker writes a simple client-side script that loops indefinitely, creating a new feedback document in each iteration.
// Attacker runs this script in a loop. // Each iteration is a billable write operation. for (let i = 0; i < 10000; i++) { db.collection("user_feedback").add({ comment: "This is spam comment #" + i, timestamp: new Date() }) .then(() => console.log("Spam document written.")) .catch((err) => console.error("Write failed, but we will retry: ", err)); }
- Outcome: The script successfully creates 10,000 new documents in a very short time. The attacker has generated 10,000 billable write operations, and the
user_feedback
collection is now filled with spam.
Mitigation¶
The vulnerability is resolved by implementing a rate-limiting mechanism in the security rules. This is typically done by maintaining a separate document that tracks the timestamp of a user's last action. The rule then checks this timestamp before allowing a new operation.
First, create a separate collection (e.g., user_metadata
) to store the last write time for each user.
// SECURE: Checks the user's last write time before allowing a new one.
match /user_feedback/{feedbackId} {
allow create: if request.auth != null &&
// Get the user's metadata document.
let lastWrite = get(/databases/$(database)/documents/user_metadata/$(request.auth.uid)).data.lastFeedbackTime;
// Allow if the last write was more than 5 seconds ago.
request.time > lastWrite + duration.value(5, 's');
}
Best Practice
After the client successfully writes a user_feedback
document, it must immediately update the lastFeedbackTime
field in the /user_metadata/$(request.auth.uid)
document to the current server timestamp. This "resets the clock" for the next operation. This can be done securely using a batched write on the client.