HIGH api rate abusefirestore

Api Rate Abuse in Firestore

How API Rate Abuse Manifests in Firestore

Firestore, Google Cloud's NoSQL document database, exposes a REST API (firestore.googleapis.com/v1/.../documents) alongside client SDKs. Its pricing model directly ties costs to document reads, writes, and deletes, making it a prime target for rate abuse attacks that can exhaust your quota and generate unexpected bills. Unlike traditional SQL databases, Firestore's real-time listeners and query model create unique abuse vectors.

Specific Firestore Attack Patterns

  • Listener Flooding: An attacker repeatedly opens WebSocket or gRPC streams via the /listen endpoint (used by SDKs for real-time updates). Each active listener counts as a document read operation per update, multiplying costs if documents change frequently.
  • Query Exhaustion: Crafting queries that force full collection scans (collectionGroup queries without indexes) or deeply nested array-contains-any with large arrays. Firestore charges per document read, even for queries that return zero results if the index must scan many documents.
  • Write Amplification: Triggering Cloud Functions (via Firestore triggers) that perform batched writes or update many subcollections. A single malicious write can cascade into hundreds of operations. For example, updating a document that has a trigger writing to 100 user subcollections.
  • Authentication Bypass for Public Endpoints: Misconfigured Firestore security rules (allow read: if true;) on a publicly accessible REST endpoint allow unauthenticated attackers to run arbitrary queries, consuming your read quota.

A real-world example: an attacker targets a /users/{userId}/messages subcollection with a query like ?orderBy=__name__ (no limit) against a collection with 10,000 messages. Each request reads all 10,000 documents, costing ~$0.06 per 100,000 reads (as of 2024 pricing). 100 such requests = $0.60, but scaled to thousands per minute, bills skyrocket.

Firestore-Specific Detection

Detecting rate abuse vulnerabilities in Firestore requires testing its REST API endpoints for missing or ineffective rate limiting. middleBrick's scanner specifically probes Firestore's API surface:

  • It sends sequential requests to endpoints like POST https://firestore.googleapis.com/v1/projects/{project}/databases/(default)/documents:runQuery with minimal valid queries.
  • It monitors for HTTP 429 Too Many Requests responses or latency spikes indicating no throttling.
  • It checks for Firestore-specific error patterns (e.g., RESOURCE_EXHAUSTED quota errors) that should trigger after a threshold but may not if rate limiting is absent at the API gateway layer.

Scanning with middleBrick
Use the web dashboard or CLI to scan your Firestore REST endpoint. The CLI command is straightforward:

middlebrick scan https://firestore.googleapis.com/v1/projects/your-project/databases/(default)/documents

The report will flag "Rate Limiting" as a category if the endpoint allows >100 requests/minute without throttling. It maps findings to OWASP API4:2023 (Unrestricted Resource Consumption) and highlights Firestore's cost-risk implications.

What to Look For in the Report
middleBrick's rate limiting check includes:

  • Severity scoring based on request throughput tolerated before blocking.
  • Verification of standard headers like Retry-After on 429 responses.
  • Detection of Firestore's native quota errors (e.g., quota exceeded in JSON body) vs proper rate limiting.

If your Firestore endpoint is behind a Google Cloud Endpoints or API Gateway, middleBrick will test the public-facing URL, not the internal Firestore service.

Firestore-Specific Remediation

Remediation focuses on layering defenses: Firestore Security Rules for authorization, Google Cloud infrastructure for rate limiting, and client-side best practices. Note: Firestore Security Rules cannot enforce rate limits directly—they are for document-level authorization. Rate limiting must occur at the API gateway or application layer.

1. Enforce App Check for All Client Traffic

App Check ensures only your authentic apps (iOS, Android, web) can access Firestore. It blocks script-based attacks from non-app origins.

// Initialize in your client app (JavaScript example)
import { initializeApp } from "firebase/app";
import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";

const app = initializeApp(firebaseConfig);
const appCheck = initializeAppCheck(app, {
  provider: new ReCaptchaV3Provider('your-recaptcha-site-key'),
  isTokenAutoRefreshEnabled: true
});

This adds an X-Firebase-AppCheck token to requests. In the Firebase console, enforce App Check for Firestore. Unauthenticated REST calls without this token will be rejected.

2. Deploy a Rate-Limiting Proxy

Use Google Cloud Endpoints or a Cloud Function as a proxy to enforce quotas. Example using Cloud Functions with express-rate-limit:

const functions = require('@google-cloud/functions-framework');
const rateLimit = require('express-rate-limit');

functions.http('firestore-proxy', async (req, res) => {
  const limiter = rateLimit({
    windowMs: 60 * 1000, // 1 minute
    max: 100, // limit each IP to 100 requests per windowMs
    message: 'Too many requests'
  });

  // Apply limiter to all routes
  limiter(req, res, async () => {
    // Proxy request to Firestore REST API
    const firestoreUrl = `https://firestore.googleapis.com/v1/projects/${process.env.GCP_PROJECT}/databases/(default)/documents${req.path}`;
    const firestoreRes = await fetch(firestoreUrl, {
      method: req.method,
      headers: { ...req.headers, host: undefined },
      body: req.method !== 'GET' ? req.body : undefined
    });
    res.status(firestoreRes.status).json(await firestoreRes.json());
  });
});

Deploy this and point your clients to the Cloud Function URL. Adjust max based on your expected user load.

3. Harden Security Rules for Query Costs

While rules can't rate-limit, they can prevent expensive queries. Use request.query constraints:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /messages/{message} {
      allow read: if request.auth != null && request.query.limit <= 50;
      // Reject queries without a limit or with large limits
    }
  }
}

This forces clients to include limit=50 max. Combine with composite indexes to avoid collection scans.

4. Monitor Quotas and Set Alerts

In Google Cloud Console, set budget alerts at 50%, 90%, etc. Use Firestore's built-in metrics (read/write operations) in Cloud Monitoring to detect spikes. middleBrick's Pro plan offers continuous monitoring and can alert you if your score drops due to new rate abuse findings.

FAQ

Q: Can Firestore's built-in quotas prevent rate abuse?
A: Firestore has project-level quotas (e.g., 10,000 writes/second), but these are hard limits that cause RESOURCE_EXHAUSTED errors for all users if exceeded. They are not a substitute for per-user rate limiting, which protects against targeted abuse from a single source.

Q: Does middleBrick scan Firestore's real-time listener endpoints?
A: middleBrick scans standard REST endpoints like /runQuery and /documents. Firestore's real-time listeners use gRPC/WebSocket protocols not directly testable via HTTP. However, if your app exposes a HTTP proxy for listeners, middleBrick can scan that endpoint. The primary risk remains the REST API for admin panels or server-to-server calls.