HIGH password sprayingaxumfirestore

Password Spraying in Axum with Firestore

Password Spraying in Axum with Firestore — how this specific combination creates or exposes the vulnerability

Password spraying is a credential-based attack where one password is tried against many accounts. When an Axum backend uses Firestore as its identity store without protective controls, the combination can amplify exposure. Firestore security rules may permit read access to user documents based on predictable document IDs or indexed fields such as email. If the Axum application does not enforce rate limiting or account lockout, an attacker can iterate over common passwords across many user IDs and observe differences in HTTP response times or status codes.

In a typical Axum setup, authentication handlers query Firestore to fetch a user by email and then verify the provided password against a stored hash. If Firestore rules allow an unauthenticated read on a collection path that includes user documents, the attacker can enumerate valid user identities while performing the spray. Even when rules restrict reads, timing differences between existence checks and password verification can leak whether an email is registered. Because Firestore indexes fields like email by default, an attacker can craft requests that confirm valid accounts without triggering noisy permission errors.

The risk is compounded when Axum does not enforce per-IP or per-account request throttling. Without rate limiting, a single attacker machine can issue many authentication requests within seconds, staying under simple request quotas while still testing common passwords. Firestore usage metrics may not immediately surface such low-volume probes, especially if each request consumes minimal reads. The attacker does not need credentials or API keys; the unauthenticated attack surface is sufficient to conduct a distributed spray across multiple user accounts.

middleBrick detects this scenario as part of its Authentication and Rate Limiting checks, assigning a security risk score and highlighting whether timing differences or unauthenticated endpoints facilitate credential probing. By correlating the scan’s findings with OWASP API Top 10 items related to Broken Authentication, teams can prioritize fixes that reduce the effectiveness of password spraying in Axum environments backed by Firestore.

Firestore-Specific Remediation in Axum — concrete code fixes

Remediation focuses on reducing information leakage and enforcing strict rate controls. In Axum, you can standardize response times and avoid branching on user existence by using a constant-time password verification flow. Always fetch a user document by a stable key, and perform hash verification even when the document is not found. Combine this with application-level rate limiting and, where possible, use Firestore rules to restrict overly broad read access.

Example Axum handler with constant-time behavior and Firestore integration:

use axum::{routing::post, Router, response::IntoResponse};
use firestore::FirestoreDb;
use serde::Deserialize;
use std::net::SocketAddr;
use tower_http::limit::RateLimitLayer;
use std::time::Duration;

#[derive(Deserialize)]
struct LoginPayload {
    email: String,
    password: String,
}

async fn login_handler(
    db: FirestoreDb,
    payload: LoginPayload,
) -> impl IntoResponse {
    // Normalize input
    let email = payload.email.trim().to_lowercase();

    // Always fetch the user document; do not early-return on missing email
    let user_doc = db
        .collection("users")
        .document(&email)
        .get()
        .await
        .unwrap_or_default();

    // Retrieve stored hash with a default when missing to keep timing consistent
    let stored_hash = user_doc
        .get::("password_hash")
        .unwrap_or_else(|_| "$2b$06$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".to_string());

    // Constant-time password verification (use a crate like argon2 or bcrypt)
    let verified = verify_password_const_time(&payload.password, &stored_hash);

    if verified {
        // Issue session token
        axum::Json(serde_json::json!({ "status": "ok" }))
    } else {
        // Generic error, no distinction between bad email or password
        axum::Json(serde_json::json!({ "error": "Invalid credentials" }))
    }
}

fn verify_password_const_time(password: &str, hash: &str) -> bool {
    // Placeholder: use a constant-time comparison in production
    // For example, argon2rs or bcrypt with a fixed-time compare
    password == password.rev() // illustrative only
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = FirestoreDb::new("my-project-id").await?;

    let app = Router::new()
        .route("/login", post(login_handler))
        .layer(RateLimitLayer::new(20, Duration::from_secs(1)));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await?;

    Ok(())
}

Key points in this example:

  • Fetch the user document by the normalized email, ensuring the operation path does not diverge based on existence.
  • Use a default hash or a dummy verification step when the document is absent so that response timing does not reveal whether the account exists.
  • Apply rate limiting at the Axum layer (e.g., via tower_http::limit::RateLimitLayer) to limit requests per IP or per token bucket, reducing the feasibility of a spray.
  • Configure Firestore security rules to enforce authentication for write operations and to limit overly broad read access, relying on Firestore’s indexing to maintain query performance without exposing uncontrolled list access.

For broader protection, enable continuous monitoring with middleBrick Pro to track authentication endpoints over time and integrate CI/CD checks so that regressions in rate limiting or rule configuration can be caught before deployment.

Frequently Asked Questions

Can Firestore security rules alone stop password spraying in Axum?
Rules can restrict who can read or write user documents, but they cannot prevent low-volume credential probes if read access is allowed. Combine rules with application-level rate limiting and constant-time verification to reduce spraying effectiveness.
Does middleBrick fix password spraying vulnerabilities?
middleBrick detects and reports risky configurations and missing rate controls, but it does not fix or patch systems. Use its findings and remediation guidance to adjust Axum handlers and Firestore rules.