HIGH cryptographic failuresfastapibasic auth

Cryptographic Failures in Fastapi with Basic Auth

Cryptographic Failures in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability

Basic Authentication in FastAPI transmits credentials as base64-encoded strings over HTTP. Base64 is not encryption and provides no confidentiality; it is easily reversible. When used without TLS, credentials are exposed in cleartext across the network, enabling credential theft via network sniffing. This is a cryptographic failure because the protocol lacks encryption of the authentication material.

Even when TLS is used, improper implementation can weaken protections. For example, failing to enforce HTTPS redirects or allowing both HTTP and HTTPS endpoints results in credentials being sent in cleartext on the non-HTTPS path. Additionally, storing or logging credentials from Basic Auth (e.g., in access logs) without hashing or masking can lead to sensitive data exposure. The standard library’s HTTPBasic and HTTPBasicCredentials provide a straightforward mechanism, but they do not enforce transport security by themselves.

During a middleBrick scan, endpoints using Basic Auth without enforced HTTPS are flagged under Data Exposure and Encryption checks. The scanner also tests for insecure credential handling, such as logging credentials in plaintext or failing to apply consistent strict transport security. These findings map to real-world attack patterns like credential replay and man-in-the-middle (MITM) attacks, which are common in OWASP API Top 10 categories such as Broken Object Level Authorization and Data Exposure.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

Remediation centers on enforcing HTTPS and avoiding the transmission or storage of raw credentials. Always redirect HTTP to HTTPS and ensure TLS is terminated at the edge or load balancer. Do not log or store Basic Auth credentials; if you must retain them for compatibility, store only salted hashes and avoid logging raw headers.

Below are concrete FastAPI examples that demonstrate insecure and secure approaches.

Insecure example: Basic Auth over HTTP

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import uvicorn

app = FastAPI()
security = HTTPBasic()

def get_current_user(credentials: HTTPBasicCredentials = Depends(security)):
    # Insecure: no transport validation, credentials handled in plaintext
    correct_username = "admin"
    correct_password = "secret"
    if credentials.username != correct_username or credentials.password != correct_password:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username

@app.get("/items/")
def read_items(username: str = Depends(get_current_user)):
    return {"username": username}

if __name__ == "__main__":
    # WARNING: running without TLS is insecure for Basic Auth
    uvicorn.run(app, host="0.0.0.0", port=80)

Secure remediation: enforce HTTPS and avoid logging credentials

from fastapi import FastAPI, Depends, HTTPException, status, Request
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
import uvicorn

app = FastAPI()
# Add HTTPS redirect middleware in production to enforce TLS
app.add_middleware(HTTPSRedirectMiddleware)

security = HTTPBasic()

# In a real deployment, validate credentials against a secure user store.
# Do not log raw credentials; mask them if necessary for debugging.
def get_current_user_secure(credentials: HTTPBasicCredentials = Depends(security)):
    correct_username = "admin"
    correct_password = "secret"
    # Use constant-time comparison to mitigate timing attacks where feasible
    if not (credentials.username == correct_username and credentials.password == correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    # Avoid logging credentials; log only masked identifiers if needed
    return credentials.username

@app.get("/secure-items/")
def read_secure_items(username: str = Depends(get_current_user_secure)):
    return {"username": username}

# Example of how to run with TLS (use real certs in production)
# uvicorn.run(app, host="0.0.0.0", port=443, ssl_keyfile="./key.pem", ssl_certfile="./cert.pem")

Additional recommendations: use middleware to enforce HTTPS, prefer token-based authentication (e.g., OAuth2 with Bearer tokens) where possible, and ensure your TLS configuration follows current best practices (strong ciphers, valid certificates). middleBrick’s scans can validate that HTTP-to-HTTPS redirects are in place and that no endpoints expose Basic Auth over cleartext.

Frequently Asked Questions

Does middleBrick test for Basic Auth vulnerabilities in scans?
Yes. middleBrick includes checks for Authentication and Data Exposure that detect whether Basic Auth is used without enforced HTTPS and flags cleartext credential transmission.
What should I do if I must use Basic Auth temporarily?
Enforce HTTPS with valid TLS certificates, redirect HTTP to HTTPS, avoid logging credentials, and treat Basic Auth as high-risk. Plan to migrate to stronger authentication such as OAuth2 or session-based tokens.