HIGH dictionary attackfastapibasic auth

Dictionary Attack in Fastapi with Basic Auth

Dictionary Attack in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability

A dictionary attack against a FastAPI service using HTTP Basic Auth leverages two realities: predictable credential names and unthrottled login endpoints. Basic Auth sends credentials in an RFC-compliant header on each request; when transport protection is absent (no TLS) or weak ciphers are allowed, interception risk rises. When FastAPI does not enforce rate limiting, an attacker can submit hundreds of username/password pairs per minute without triggering defenses.

During a black-box scan, middleBrick tests unauthenticated attack surfaces and checks whether the API leaks information that helps narrow the dictionary. For example, some implementations return distinct HTTP status codes or response bodies for 401 vs 403, or differ in timing when a valid username is supplied versus a randomly guessed one. These observable differences let an attacker iteratively refine guesses without ever locking accounts. Because Basic Auth has no built-in retry policy, the attack surface is effectively the login path itself, often a single route like /login or any protected endpoint that accepts credentials.

middleBrick’s Authentication and Rate Limiting checks run in parallel to detect whether requests are accepted without lockout, whether responses are consistent to avoid user enumeration, and whether transport security is enforced. If the scan uncovers that valid usernames elicit different responses or that no account lockout exists, the findings map to the Authentication and Rate Limiting categories in the dashboard. These findings highlight that the FastAPI endpoint is susceptible to online credential guessing, where a moderately sized wordlist can yield valid pairs, especially when users choose weak passwords.

Real-world attack patterns mirror this behavior. For instance, attackers may combine a small set of known default credentials with common passwords and iterate programmatically. If the API does not implement exponential backoff or token-based lockout, the dictionary attack can succeed quickly. middleBrick also inspects whether the server advertises security headers that discourage automated abuse and whether TLS configurations meet baseline standards. Without enforced protections, the FastAPI service remains exposed to credential compromise and subsequent lateral movement within the environment.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

Remediation focuses on eliminating user enumeration, enforcing transport security, and introducing adaptive throttling. FastAPI allows you to customize the dependency that validates credentials, so you can centralize logic and ensure every path behaves identically for valid and invalid inputs.

First, always serve Basic Auth over TLS. Use an HSTS header and reject cleartext HTTP. Below is a minimal, secure FastAPI setup that enforces HTTPS and standardizes responses:

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.responses import JSONResponse
import hashlib
import hmac

app = FastAPI()
security = HTTPBasic()

# In production, store password hashes derived with a slow KDF
USERS = {
    "alice": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"  # "password" SHA-256 example only; use argon2 or scrypt in practice
}

def verify_credentials(credentials: HTTPBasicCredentials = Depends(security)):
    expected = USERS.get(credentials.username)
    if expected is None:
        # Always perform a dummy hash to avoid timing leaks
        dummy = hashlib.sha256(credentials.password.encode()).hexdigest()
        hmac.compare_digest(dummy, dummy)  # constant-time no-op
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={"message": "Invalid credentials"}
        )
    if not hmac.compare_digest(expected, hashlib.sha256(credentials.password.encode()).hexdigest()):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={"message": "Invalid credentials"}
        )
    return credentials.username

@app.get("/secure")
def secure_route(username: str = Depends(verify_credentials)):
    return {"user": username, "data": "protected"}

This pattern ensures that missing users and wrong passwords return the same status code and body shape, reducing information leakage. The use of hmac.compare_digest mitigates timing attacks on hash comparison.

Second, add rate limiting at the dependency or middleware layer. FastAPI does not provide built-in request throttling, so integrate a token bucket or sliding window via a lightweight library or a reverse proxy. For example, using a simple in-memory counter with expiration can curb aggressive bursts:

from fastapi import Request
import time

RATE_LIMIT = 5  # attempts
WINDOW = 60     # seconds
attempts = {}  # keyed by IP or username

def rate_limit(request: Request, username: str):
    key = f"{request.client.host}:{username}"
    now = time.time()
    entry = attempts.get(key, {"count": 0, "start": now})
    if now - entry["start"] > WINDOW:
        entry = {"count": 1, "start": now}
    else:
        entry["count"] += 1
    attempts[key] = entry
    if entry["count"] > RATE_LIMIT:
        raise HTTPException(status_code=429, detail="Too many attempts")

# Then call rate_limit inside verify_credentials after username extraction

Third, consider moving away from Basic Auth in favor of token-based flows where possible. If you must retain Basic Auth, pair it with an API gateway or load balancer that enforces global rate limits and WAF rules. middleBrick’s Pro plan enables continuous monitoring and CI/CD integration so that risk scores are checked on a configurable schedule, helping you catch regressions before deployment.

Frequently Asked Questions

Why does FastAPI with Basic Auth leak information via status codes even when I return the same HTTP code?
Even with a uniform 401 response, subtle timing differences or body size variations can reveal whether a username exists. Use constant-time operations and identical payload shapes for all outcomes to reduce user enumeration.
Can middleBrick detect dictionary attack risks in unauthenticated scans?
Yes. middleBrick tests authentication and rate limiting in parallel during unauthenticated scans, identifying whether distinct responses or missing lockout mechanisms enable dictionary attacks.