Distributed Denial Of Service in Fastapi with Basic Auth
Distributed Denial Of Service in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability
When a Fastapi service relies solely on HTTP Basic Authentication and is exposed to the public internet, the authentication mechanism itself can become an amplification vector for Distributed Denial Of Service (DDoS). Basic Auth transmits credentials in an easily reversible format (base64) and typically requires the server to validate credentials on every request, often involving a backend identity provider or directory lookup. If the endpoint lacks sufficient rate limiting or if the authentication path is computationally heavier than expected (for example, validating credentials against a slow directory or performing additional role checks on each request), an attacker can issue many concurrent unauthenticated or low-privilege requests to consume server resources.
In a black-box scan, middleBrick tests the unauthenticated attack surface and checks for missing Rate Limiting alongside Authentication. Without rate controls, an unauthenticated caller can repeatedly trigger the Basic Auth verification logic, tying up worker processes or threads. In Fastapi, if the authentication logic is not optimized or if the dependency is invoked on every route without short-circuiting for public endpoints, this can lead to high CPU usage or thread exhaustion under load. The scan also flags endpoints where authentication is required but enforcement is inconsistent (e.g., some routes protected, others not), which can allow attackers to focus effort on the less-protected paths.
Because middleBrick runs 12 security checks in parallel, the Authentication and Rate Limiting checks work together to surface this risk: weak or missing rate limits combined with Basic Auth validation can result in a low score for Availability. The scan does not assume an internal architecture, but the findings highlight that an attacker can generate enough requests to exhaust connection pools or trigger expensive credential validation, contributing to denial of service for legitimate users.
Basic Auth-Specific Remediation in Fastapi — concrete code fixes
To reduce DDoS risk when using Basic Auth in Fastapi, combine lightweight authentication with strict rate limiting and avoid expensive per-request work. Below are concrete, working examples that demonstrate a safer approach.
1. Basic Auth with fastapi.security.HTTPBasic and optimized validation
Use HTTPBasic for simplicity, but ensure credentials are validated efficiently (e.g., via a fast in-memory cache or a precomputed hash) and that expensive directory lookups are minimized. Do not perform heavy computation or multiple remote calls on every request.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets
import time
app = FastAPI()
security = HTTPBasic()
# Example: simple in-memory credential store (for demo only; use a secure backend in production)
VALID_USERNAME = "apiuser"
# Store a pre-hashed value; avoid storing plaintext passwords
VALID_PASSWORD_HASH = secrets.token_hex(32) # Replace with a proper hash of your password
# Rate-limiting helper: track request timestamps per credentials
from collections import deque
request_log = deque()
RATE_LIMIT_WINDOW = 60 # seconds
MAX_REQUESTS_PER_WINDOW = 100
def is_rate_limited():
now = time.time()
# Remove outdated entries
while request_log and request_log[0] <= now - RATE_LIMIT_WINDOW:
request_log.popleft()
if len(request_log) >= MAX_REQUESTS_PER_WINDOW:
return True
request_log.append(now)
return False
def get_current_user(credentials: HTTPBasicCredentials = Depends(security)):
if is_rate_limited():
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Rate limit exceeded",
)
# Compare pre-hashed credentials efficiently; avoid heavy work here
if credentials.username != VALID_USERNAME:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
# Use a constant-time comparison for the password hash in real use
if credentials.password != VALID_PASSWORD_HASH: # Replace with proper hash check
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
return credentials.username
@app.get("/items/")
def read_items(current_user: str = Depends(get_current_user)):
return {"message": f"Hello, {current_user}"}
2. Apply rate limiting at the API gateway or router level
In production, offload per-request work by enforcing rate limits at the edge or via a dependency that is shared across routes. This prevents an unbounded number of authentication checks under load.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.middleware.base import BaseHTTPMiddleware
import time
app = FastAPI()
security = HTTPBasic()
class RateLimitMiddleware(BaseHTTPMiddleware):
def __init__(self, app, max_requests=100, window=60):
super().__init__(app)
self.max_requests = max_requests
self.window = window
self.requests = []
async def dispatch(self, request, call_next):
now = time.time()
self.requests = [t for t in self.requests if t > now - self.window]
if len(self.requests) >= self.max_requests:
from starlette.responses import JSONResponse
return JSONResponse({"detail": "Rate limit exceeded"}, status_code=429)
self.requests.append(now)
response = await call_next(request)
return response
app.add_middleware(RateLimitMiddleware, max_requests=100, window=60)
# Then mount routes as usual; authentication dependency can be reused
@app.get("/public/")
def public_endpoint():
return {"public": True}
3. Use dependency short-circuiting and avoid redundant checks
Ensure that authentication dependencies are not applied to endpoints that do not require them, and avoid re-validating credentials when a lightweight token or session can be used after initial validation.
| Check | Risk if omitted | Recommendation |
|---|---|---|
| Rate Limiting | High CPU or connection pool exhaustion under request floods | Enforce per-identity or per-client limits at middleware or gateway |
| Credential validation efficiency | Slow verification increases latency and resource usage | Use fast lookups and avoid remote calls on each request |
| Scope minimization | Unauthenticated paths exposed due to misconfigured dependencies | Apply auth dependencies only where needed |