Bleichenbacher Attack in Fastapi with Basic Auth
Bleichenbacher Attack in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability
A Bleichenbacher attack is a cryptographic side-channel attack originally described against PKCS#1 v1.5 padding in RSA decryption. In the API context, the term is often used to describe an attacker who probes an authentication endpoint that performs per-request cryptographic work (e.g., verifying a password hash or an HMAC) and observes timing differences that reveal information about validity. When Fastapi is combined with HTTP Basic Auth, the risk arises if the server’s credential verification logic is non-constant-time and the server returns different observable behavior—such as HTTP status codes, response times, or error messages—depending on whether the password hash or MAC is correct.
Consider a Fastapi endpoint that uses Basic Auth and performs a manual check like comparing a stored hash or HMAC. If the comparison short-circuits on the first mismatching byte (common with naive string or byte equality checks), an attacker can send many requests with slightly modified credentials and measure response times. A consistently slower response for certain password bytes allows the attacker to iteratively guess the secret, effectively performing a padding-style adaptive chosen-ciphertext attack adapted to authentication. Even when the Basic Auth credentials are correct, Fastapi may still return 401 for other reasons; if those 401 responses differ in size, headers, or timing from 200 responses, the attacker gains additional signals. In a black-box scan, middleBrick tests unauthenticated attack surfaces and flags cases where authentication endpoints appear to leak validity through timing or response differences, which is one of the 12 security checks run in parallel.
In Fastapi, a typical vulnerable pattern is to manually decode the Authorization header, extract the password, and compare it with a stored value using Python’s default equality. Because Python’s == for bytes can short-circuit, and because frameworks may raise exceptions or return different status codes based on malformed input, the observable behavior becomes information leakage. middleBrick’s LLM/AI Security checks do not apply here, but its standard authentication and input validation checks can detect endpoints where authentication logic might be susceptible to timing-based inference. The scanner cross-references the OpenAPI spec with runtime findings; if the spec documents Basic Auth but the implementation does not enforce constant-time checks or rate limiting, the finding is surfaced with severity and remediation guidance.
Basic Auth-Specific Remediation in Fastapi — concrete code fixes
To mitigate Bleichenbacher-style side-channel risks in Fastapi with HTTP Basic Auth, ensure that credential verification runs in constant time and that error paths do not leak validity. Use framework utilities that abstract safe comparison and avoid manual byte-by-byte checks. Below are two concrete approaches: one using a safe comparison helper, and one using HTTPBearer with scopes to reduce custom logic.
Example 1: Constant-time comparison with explicit 401 responses
This example decodes Basic Auth manually but uses hmac.compare_digest (constant-time) and ensures identical response shape and status code for valid and invalid credentials to minimize timing and error-message leakage.
from fastapi import Fastapi, Depends, HTTPException, Security, Header, Response
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import base64
import secrets
import hmac
app = Fastapi()
security = HTTPBasic()
# A stored secret, e.g., a password or a server-side shared secret
STORED_SECRET = b"super-secret-token-12345"
def verify_credentials(credentials: HTTPBasicCredentials) -> bool:
# Decode the provided credentials
try:
decoded = base64.b64decode(credentials.credentials)
except Exception:
decoded = b""
# Use constant-time comparison to avoid timing leaks
return hmac.compare_digest(decoded, STORED_SECRET)
@app.get("/secure")
async def secure_endpoint(response: Response, credentials: HTTPBasicCredentials = Security(security)):
# Always perform the same work and return the same response shape
if not verify_credentials(credentials):
response.status_code = 401
return {"error": "unauthorized"}
return {"message": "ok"}
Example 2: Using OAuth2PasswordBearer-style dependency with hashed passwords
For password-based flows, store a hash (e.g., argon2 or bcrypt), and compare using the framework’s safe utilities. This example uses a dummy user database and shows how to avoid leaking which part of the credential is wrong.
from fastapi import Fastapi, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import base64
import hashlib
import hmac
app = Fastapi()
security = HTTPBasic()
# Simulated user store; in practice use a database with a proper password hash
USERS = {
"alice": hashlib.sha256(b"correct-horse-battery-staple").hexdigest()
}
def get_user_password_hash(username: str):
# Return a fixed-length dummy hash to prevent username enumeration
return USERS.get(username, "0" * 64)
def verify_basic_auth(credentials: HTTPBasicCredentials = Security(security)):
try:
decoded = base64.b64decode(credentials.credentials)
username, password = decoded.split(b":", 1)
username = username.decode("utf-8")
except Exception:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Basic"},
)
expected_hash = get_user_password_hash(username)
provided_hash = hashlib.sha256(password).hexdigest()
if not hmac.compare_digest(expected_hash, provided_hash):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Basic"},
)
return username
@app.get("/items")
async def read_items(user: str = Depends(verify_basic_auth)):
return {"user": user, "items": ["a", "b"]}
Additional defenses complement these code-level fixes: enforce rate limiting on authentication endpoints to reduce adaptive attack feasibility, and ensure consistent response sizes and headers for success and error cases to minimize observable side channels. middleBrick’s checks for authentication, input validation, and rate limiting can highlight where implementations deviate from safer patterns. For teams needing ongoing oversight, the Pro plan provides continuous monitoring and can integrate into CI/CD pipelines to fail builds if risk scores exceed configured thresholds.