HIGH http request smugglingfirestore

Http Request Smuggling in Firestore

How Http Request Smuggling Manifests in Firestore

Http Request Smuggling in Firestore contexts typically occurs when applications mishandle chunked transfer encoding or content-length headers when communicating with Firestore's REST API or when Firestore data is proxied through multiple layers. The vulnerability arises from ambiguous parsing of HTTP requests between different servers or services in the request chain.

A common Firestore-specific scenario involves applications that proxy requests to Firestore's REST API while simultaneously handling chunked encoding. Consider a Node.js application using the Firebase Admin SDK that forwards requests to Firestore:

app.post('/api/firestore', async (req, res) => {
  const firestore = admin.firestore();
  const data = await req.body; // May not fully parse chunked requests
  const docRef = firestore.collection('users').doc();
  await docRef.set(data);
  res.json({ success: true });
});

The vulnerability manifests when a malicious client sends a request with conflicting Content-Length and Transfer-Encoding headers. The frontend server might parse the request one way, while Firestore's backend interprets it differently:

POST /api/firestore HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 123
Transfer-Encoding: chunked

[malicious chunk data here]

Firestore's REST API, when accessed directly or through improperly configured proxies, can be susceptible to smuggling attacks that allow attackers to:

  • Inject additional Firestore operations by smuggling requests after the initial payload
  • Access or modify documents belonging to other users through IDOR-style attacks
  • Trigger unintended database operations by manipulating request boundaries

Another Firestore-specific manifestation occurs with Firestore's batch operations. When applications process batch writes without proper request validation, smuggling can allow attackers to append additional operations:

POST /firestore/batch HTTP/1.1
Content-Type: application/json
Content-Length: 200

{
  "writes": [
    { "update": { "name": "projects/xxx/databases/(default)/documents/users/1", "fields": { "role": "user" } } }
  ]
}
POST /firestore/batch HTTP/1.1
Content-Type: application/json

{
  "writes": [
    { "update": { "name": "projects/xxx/databases/(default)/documents/users/1", "fields": { "role": "admin" } } }
  ]
}

The second POST request gets smuggled into the first, potentially escalating privileges without proper authorization checks.

Firestore-Specific Detection

Detecting Http Request Smuggling in Firestore environments requires both static analysis and dynamic testing. The key is to identify configurations where request parsing ambiguity can occur.

Static detection should focus on:

const patterns = [
  // Look for unsafe request handling
  /req\.body/i,
  // Check for missing content-length validation
  /content-length/i,
  // Identify chunked encoding handling
  /transfer-encoding/i,
  // Find Firestore batch operations
  /batch\.write/i,
  // Check for proxy configurations
  /proxy/i,
  // Look for missing request size limits
  /limit\s*:\s*undefined/i
];

Dynamic testing with middleBrick specifically targets Firestore endpoints by:

  • Sending requests with conflicting Content-Length and Transfer-Encoding headers to Firestore REST API endpoints
  • Testing batch operation endpoints with malformed JSON structures
  • Verifying proper request size limits are enforced
  • Checking for proper validation of Firestore document paths and operations

middleBrick's scanning methodology for Firestore includes:

// Example of smuggling test patterns
const smugglingTests = [
  {
    name: 'Conflicting headers',
    request: {
      method: 'POST',
      path: '/firestore/batch',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': '100',
        'Transfer-Encoding': 'chunked'
      },
      body: '{ "writes": [] }'
    }
  },
  {
    name: 'Chunked injection',
    request: {
      method: 'POST',
      path: '/firestore/write',
      headers: {
        'Content-Type': 'application/json',
        'Transfer-Encoding': 'chunked'
      },
      body: '4\n{\n8\n"test": \n0\n'
    }
  }
];

Additional detection focuses on Firestore's security rules. While rules don't prevent smuggling at the HTTP layer, they can limit the blast radius:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if 
        request.auth != null &&
        request.auth.token.email_verified &&
        request.auth.token.email.matches('.*@yourdomain\.com$');
    }
  }
}

middleBrick's LLM security module also checks for potential AI-related smuggling scenarios where large language models might be used to generate or parse malicious requests targeting Firestore endpoints.

Firestore-Specific Remediation

Remediating Http Request Smuggling in Firestore applications requires a defense-in-depth approach focusing on both HTTP layer security and Firestore-specific protections.

Primary HTTP layer fixes:

// Express.js middleware for request sanitization
app.use((req, res, next) => {
  // Remove conflicting headers
  if (req.headers['transfer-encoding'] && req.headers['content-length']) {
    delete req.headers['transfer-encoding'];
  }
  
  // Enforce strict content-length validation
  if (req.headers['content-length']) {
    const expectedLength = parseInt(req.headers['content-length']);
    const actualLength = req.socket.bytesRead;
    if (actualLength !== expectedLength) {
      return res.status(400).json({ error: 'Invalid content length' });
    }
  }
  
  next();
});

Using Firebase Admin SDK with proper configuration:

const admin = require('firebase-admin');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://your-project.firebaseio.com'
});

// Secure Firestore operations
async function safeWrite(collection, docId, data) {
  const db = admin.firestore();
  
  // Validate document path
  if (!/^[a-zA-Z0-9_-]+$/.test(docId)) {
    throw new Error('Invalid document ID');
  }
  
  // Validate data structure
  if (typeof data !== 'object' || data === null) {
    throw new Error('Invalid data format');
  }
  
  const docRef = db.collection(collection).doc(docId);
  await docRef.set(data, { merge: false });
}

// Batch operations with validation
async function safeBatchWrite(operations) {
  const db = admin.firestore();
  const batch = db.batch();
  
  operations.forEach(op => {
    if (!op.collection || !op.docId || !op.data) {
      throw new Error('Invalid batch operation');
    }
    
    const docRef = db.collection(op.collection).doc(op.docId);
    batch.set(docRef, op.data, { merge: false });
  });
  
  await batch.commit();
}

Implementing strict request size limits and timeouts:

// Express.js configuration
app.use(express.json({
  limit: '1mb', // Enforce reasonable size limits
  strict: true // Require valid JSON
}));

app.use((req, res, next) => {
  // Set timeout for request processing
  req.setTimeout(30000, () => {
    res.status(408).json({ error: 'Request timeout' });
  });
  next();
});

Firestore security rules enhancement for defense-in-depth:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Restrict batch operations to specific patterns
    match /{collection}/batch/{doc=**} {
      allow write: if request.auth != null &&
                   request.auth.token.email_verified &&
                   request.resource.data.writes.size() <= 20 && // Limit batch size
                   allOperationsValid(request.resource.data.writes);
    }
    
    // Validate document paths
    match /{collection}/{document=**} {
      allow read, write: if 
        request.auth != null &&
        isValidDocumentPath(collection, document) &&
        isValidUserData(request.resource.data);
    }
  }
}

function allOperationsValid(writes) {
  return writes.matches('[
    {
      "operation": "write",
      "collection": string,
      "document": string,
      "data": object
    }
  ]');
}

function isValidDocumentPath(collection, document) {
  return collection.matches('^[a-zA-Z0-9_-]+$') &&
         document.matches('^[a-zA-Z0-9_-]+$');
}

Using middleBrick's continuous monitoring to verify fixes:

// middleBrick CLI for ongoing verification
// Install: npm install -g middlebrick
// Scan: middlebrick scan https://your-firestore-api.example.com
// GitHub Action integration:
// - name: Scan Firestore API
//   uses: middleBrick/middlebrick-action@v1
//   with:
//     url: ${{ secrets.FIRESTORE_API_URL }}
//     fail-on-severity: high
//     token: ${{ secrets.GITHUB_TOKEN }}

Frequently Asked Questions

How does Http Request Smuggling specifically affect Firestore batch operations?
Http Request Smuggling can exploit Firestore batch operations by allowing attackers to append additional write operations to a single HTTP request through malformed headers or chunked encoding. This can bypass authorization checks if the application doesn't properly validate each operation in the batch. The vulnerability is particularly dangerous because batch operations are designed to be atomic, so smuggled operations execute as part of the legitimate transaction.
Can Firestore security rules prevent Http Request Smuggling attacks?
Firestore security rules cannot prevent HTTP-level smuggling attacks since they operate at the database layer, not the HTTP layer. However, rules provide defense-in-depth by validating document paths, limiting batch sizes, and restricting operations to authenticated users. Combined with proper HTTP request sanitization, security rules help contain the impact if smuggling succeeds.