HIGH zone transferfirestore

Zone Transfer in Firestore

How Zone Transfer Manifests in Firestore

In Firestore, "zone transfer" refers to a data exposure pattern where an attacker can read entire collections or cross-tenant data due to overly permissive security rules. This is analogous to a DNS zone transfer (AXFR/IXFR) that reveals all DNS records in a zone. In Firestore, the "zone" is a logical data boundary—typically a collection or a set of documents belonging to a specific tenant or user. When security rules fail to enforce proper isolation, an authenticated user (or even an unauthenticated attacker if rules are public) may query or read documents beyond their authorized scope.

Firestore's data model is hierarchical: databases contain collections, which contain documents, which may contain subcollections. A common multi-tenant design uses a tenant identifier in the document path (e.g., tenants/{tenantId}/projects/{projectId}) or as a field within documents. If rules only check for authentication (request.auth != null) without validating the tenant context, any signed-in user can access all documents in a collection—effectively performing a "zone transfer" of the entire dataset.

Another manifestation involves collection group queries. Firestore allows querying across all subcollections with a given name (e.g., SELECT * FROM orders across /users/*/orders). If the security rule for the orders subcollection does not verify the parent document's tenant, an attacker can use a collection group query to retrieve orders from every user in every tenant.

Consider this vulnerable rule set:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Vulnerable: allows any authenticated user to read any project
    match /tenants/{tenantId}/projects/{projectId} {
      allow read: if request.auth != null;
    }

    // Vulnerable: collection group rule for 'orders' subcollections
    match /{path=**}/orders/{orderId} {
      allow read: if request.auth != null;
    }
  }
}

An attacker with a valid Firebase Authentication token could:

  • Read every project document in every tenant by directly accessing /tenants/any-tenant/projects/any-project.
  • Execute a collection group query on orders to retrieve all orders across all users and tenants.

This violates the principle of least privilege and can lead to massive data breaches, especially in SaaS applications serving multiple organizations.

Firestore-Specific Detection

Detecting zone transfer vulnerabilities in Firestore requires testing both the API layer (if you have a backend that accesses Firestore) and the Firestore security rules directly. Since middleBrick performs black-box scanning of API endpoints, it can identify data exposure issues by probing endpoints that return Firestore data.

Manual Detection: Use the Firebase Emulator Suite to simulate requests with different authentication contexts. The Firestore rules simulator in the Firebase Console lets you test a read/write operation against a specific document path and see if it's allowed. For collection group queries, simulate a query on the subcollection name. You can also write integration tests using the Firebase Admin SDK to attempt unauthorized reads.

Automated Detection with middleBrick: middleBrick's Data Exposure check will send requests to your API endpoints (e.g., GET /api/projects) and analyze the responses. If the endpoint returns data from multiple tenants or an entire collection without proper authorization (e.g., by using different user tokens or no token), middleBrick flags a high-severity finding. For example, if your API lists projects without filtering by the user's tenant, middleBrick might detect that two different user accounts receive overlapping or identical project lists, indicating a zone transfer.

middleBrick also tests for unauthenticated access. If an endpoint that should require authentication returns data without a token or with an invalid token, it will be flagged. The scanner's parallel checks include authentication bypass and data exposure, which together can reveal zone transfer vulnerabilities.

Example scan output snippet from middleBrick for a vulnerable endpoint:

{
  "finding": "Data Exposure",
  "severity": "high",
  "endpoint": "/api/projects",
  "evidence": "Response contains projects from multiple tenants (tenantA, tenantB) when accessed with user token for tenantA",
  "remediation": "Ensure API filters results by the authenticated user's tenant identifier."
}

Note: middleBrick does not inspect Firestore rules directly; it tests the runtime behavior of your API. Therefore, your API must expose endpoints that interact with Firestore for the scanner to detect issues.

Firestore-Specific Remediation

Remediating zone transfer vulnerabilities in Firestore involves tightening security rules to enforce per-tenant or per-user isolation. The fix depends on your data model: whether the tenant identifier is in the document path or as a field.

Option 1: Tenant ID in Path

Structure your collections so that the tenant ID is part of the document path. Then, write rules that match the tenant segment and compare it to the user's tenant claim (stored in request.auth.token.tenant_id or similar).

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Secure rule: only allow access within the user's tenant
    match /tenants/{tenantId}/{document=**} {
      allow read, write: if request.auth != null && request.auth.token.tenant_id == tenantId;
    }
  }
}

Here, {document=**} matches any document or subcollection under the tenant. The rule checks that the tenantId in the path matches the tenant ID in the user's authentication token. This prevents a user from accessing /tenants/other-tenant/....

Option 2: Tenant ID as a Field

If you cannot include the tenant ID in the path (e.g., legacy data model), store the tenant ID as a field in each document and validate it in rules. However, note that Firestore rules cannot perform queries; they only evaluate on a specific document. For reads of a single document, you can check the field:

match /projects/{projectId} {
  allow read: if request.auth != null && resource.data.tenant_id == request.auth.token.tenant_id;
}

But for collection reads (e.g., GET /projects), the rule above applies to each document individually. If your API returns a list of projects, the backend must query only projects where tenant_id == user's tenant. The API layer must enforce this; Firestore rules alone cannot filter collection results. Therefore, combine rule-level checks with backend query filters.

Collection Group Queries

For subcollections like orders under different parent documents, use a collection group rule that verifies the parent's tenant. This requires the parent document (e.g., users/{userId}) to contain the tenant ID, and the rule must fetch that parent document to check.

match /{path=**}/orders/{orderId} {
  allow read: if request.auth != null &&
    // Extract the parent path (e.g., 'users/uid123')
    let parentPath = /databases/$(database)/documents/$(path)/..;
    // Get the parent document and check its tenant_id field
    get(parentPath).data.tenant_id == request.auth.token.tenant_id;
}

This rule works for any orders subcollection at any depth. It retrieves the immediate parent document and compares its tenant_id to the user's tenant. Ensure the parent document exists and contains the field; otherwise, the rule will fail.

Additional Best Practices:

  • Use Firebase Authentication custom claims to store the tenant ID, as claims are automatically available in request.auth.token.
  • Never use allow read: if true; or allow read: if request.auth != null; without tenant checks.
  • Test rules thoroughly with the emulator, including collection group queries.
  • In your backend API, always construct Firestore queries that include a tenant filter (e.g., .where('tenant_id', '==', userTenantId)).

By implementing these rule patterns, you close the zone transfer vector and ensure that users can only access data within their authorized zone.

Frequently Asked Questions

What is zone transfer in Firestore?
In Firestore, zone transfer describes a data exposure vulnerability where overly permissive security rules allow an authenticated user to read entire collections or cross-tenant data. It's analogous to a DNS zone transfer that reveals all records in a DNS zone. This typically occurs when rules only check for authentication without validating tenant or user isolation, enabling attackers to access data beyond their authorization scope.
How does middleBrick detect Firestore data exposure?
middleBrick performs black-box scanning of your API endpoints. It sends requests with different authentication contexts (e.g., valid user token, no token) and analyzes responses. If an endpoint returns data from multiple tenants or entire collections without proper authorization—such as two different users receiving overlapping datasets—middleBrick flags a Data Exposure finding. The scanner does not inspect Firestore rules directly; it tests runtime behavior of your API layer.