HIGH dictionary attackfastapi

Dictionary Attack in Fastapi

How Dictionary Attack Manifests in FastAPI

In FastAPI, a dictionary attack (often part of credential stuffing) targets authentication endpoints, typically /token or custom login routes. The attack exploits the absence of robust rate limiting and weak password policies. FastAPI's convenience features can inadvertently create vulnerable patterns.

Attack Pattern 1: Unprotected Login Endpoint
A common FastAPI setup uses OAuth2PasswordRequestForm with a simple dependency that checks credentials against a database without throttling:

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordRequestForm

app = FastAPI()

# UNSAFE: No rate limiting on this endpoint
@app.post('/token')
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = await get_user(form_data.username)
    if not user or not verify_password(form_data.password, user.hashed_password):
        raise HTTPException(status_code=400, detail='Incorrect credentials')
    return {'access_token': create_token(user)}

An attacker can script thousands of attempts per minute using common passwords (e.g., from breach collections like RockYou) against this endpoint. FastAPI's async nature handles high concurrency effortlessly, amplifying the attack's speed.

Attack Pattern 2: Missing Account Lockout
FastAPI does not enforce account lockout policies. If the authentication logic only returns generic 'Invalid credentials' errors without tracking failed attempts, attackers can probe indefinitely without triggering alerts.

Attack Pattern 3: Password Hashing Weakness
Using fast hashes (like plain SHA-256) instead of adaptive algorithms (bcrypt, Argon2) enables rapid password cracking. A FastAPI app using passlib with sha256_crypt is vulnerable:

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=['sha256_crypt'], deprecated='auto')  # UNSAFE

# Fast hashing allows billions of guesses/sec on GPUs
hashed = pwd_context.hash('password123')

Attack Pattern 4: Token Endpoint Enumeration
If the /token endpoint reveals whether a username exists via distinct error messages or timing differences, attackers can first build a valid username dictionary before launching the password spray.

FastAPI-Specific Detection

Detecting dictionary attack vulnerabilities in FastAPI requires examining both the OpenAPI spec and runtime behavior.

1. Static Analysis (OpenAPI/Swagger)
Inspect the spec for authentication flows. A missing securitySchemes definition or lack of rateLimit extensions in the /token path is a red flag. middleBrick's OpenAPI parser resolves $ref to find shared security schemes and flags missing rate limiting declarations.

2. Runtime Scanning with middleBrick
middleBrick's black-box scanner tests the live /token endpoint (or any auth endpoint) for rate limiting absence. It sends sequential authentication attempts with invalid credentials and measures response uniformity and speed. If responses are consistently 400 with no 429 Too Many Requests after 10+ attempts, it flags 'Rate Limiting Missing' with high severity.

To scan a FastAPI app:

# Using middleBrick CLI (npm package)
npm install -g middlebrick
middlebrick scan https://api.your-fastapi-app.com/token

The report will show a category breakdown under 'Rate Limiting' and likely 'Authentication' issues. The Pro plan's continuous monitoring can detect if rate limits are removed in a later deployment.

3. Manual Testing
Use curl to test response consistency:

for i in {1..20}; do curl -X POST 'https://api.example.com/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'username=testuser&password=wrongpassword' -i; done

If all responses are 200 or 400 with identical bodies and no delays, rate limiting is likely absent. middleBrick automates this with adaptive timing analysis.

FastAPI-Specific Remediation

Remediation leverages FastAPI's middleware ecosystem and secure libraries. All fixes should be implemented server-side.

Fix 1: Implement Rate Limiting
Use slowapi or fastapi-limiter. Example with slowapi (Redis-backed):

from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from fastapi import Request

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

@app.post('/token')
@limiter.limit('5/minute')  # 5 attempts per minute per IP
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    # ... existing logic

Fix 2: Use Adaptive Password Hashing
Switch to passlib with argon2 or bcrypt:

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=['argon2'], deprecated='auto')  # SAFE

# In user registration/update
hashed_password = pwd_context.hash(plain_password)

Fix 3: Uniform Error Responses & Account Lockout
Never reveal if a username exists. Use a constant-time check:

import time
from typing import Optional

async def verify_user(username: str, password: str) -> Optional[User]:
    user = await get_user(username)
    # Always perform hash check, even if user is None (with dummy hash)
    dummy_hash = '$argon2id$v=19$m=65536,t=3,p=4$c2FsdFZhbHVl$fakehash'
    hash_to_verify = user.hashed_password if user else dummy_hash
    is_valid = pwd_context.verify(password, hash_to_verify)
    
    if user and is_valid:
        return user
    # Optional: increment failed_attempts in DB, lock after 5 tries
    return None

@app.post('/token')
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = await verify_user(form_data.username, form_data.password)
    if not user:
        # Constant delay to prevent timing attacks
        time.sleep(0.1)
        raise HTTPException(status_code=400, detail='Incorrect credentials')
    return {'access_token': create_token(user)}

Fix 4: Add CAPTCHA for Suspicious Activity
Integrate fastapi-captcha or external services after 3 failed attempts from an IP.

Note: middleBrick only detects and reports these issues. Remediation requires code changes as shown. After fixes, re-scan with middleBrick to confirm the 'Rate Limiting' and 'Authentication' scores improve.

Frequently Asked Questions

Does middleBrick fix dictionary attack vulnerabilities automatically?
No. middleBrick is a detection and reporting tool only. It identifies missing rate limiting, weak password hashing, and other issues, then provides remediation guidance like the code examples above. You must implement the fixes in your FastAPI codebase.
Can middleBrick scan my local FastAPI development server?
Yes, if your local server is accessible via a public URL (using tools like ngrok). middleBrick requires a publicly reachable endpoint to perform black-box scanning. It does not require credentials but must be able to send HTTP requests to your /token or login route.