HIGH replay attackfastapiapi keys

Replay Attack in Fastapi with Api Keys

Replay Attack in Fastapi with Api Keys — how this specific combination creates or exposes the vulnerability

A replay attack occurs when an attacker intercepts a valid request and retransmits it later to produce an unintended effect. In Fastapi, using only API keys as the sole authentication mechanism can make an API susceptible to replay attacks because the key itself is often static and does not inherently include protection against request duplication. If an API key is transmitted over an unencrypted channel or logged inadvertently, an attacker who observes the request—including the key in headers or query parameters—can replay the exact HTTP request to the same endpoint. Since the server validates only the presence and correctness of the API key, the duplicated request is accepted as legitimate.

Consider an endpoint that performs a financial transfer or changes a user’s email. If the request lacks a nonce, timestamp, or other per-request uniqueness, an attacker can capture the request using common network tools and resend it multiple times. In a black-box scan, middleBrick tests such unauthenticated attack surfaces and flags missing replay protections as a finding under the Authentication and Input Validation checks. The scanner does not assume internal implementation details; it observes that repeated, identical requests succeed when they should be treated as suspicious.

Another dimension involves how API keys are stored and transmitted. Developers sometimes embed keys in JavaScript or mobile clients, or log full request headers including keys, which increases exposure risk. Because middleBrick also checks for Data Exposure and Encryption, it can detect whether requests are transmitted without TLS or if sensitive information appears in logs that could facilitate replay. Even when API keys are rotated, the absence of request-level protections means that any previously captured valid request remains usable until the key itself is rotated and clients update their calls.

In an OpenAPI specification, API keys are commonly modeled using an apiKey security scheme with an in header, in query, or in cookie location. middleBrick resolves $ref paths across OpenAPI 2.0, 3.0, and 3.1 documents and cross-references these definitions with runtime behavior. If the spec describes key-based authentication but the implementation does not enforce replay countermeasures, the scan correlates this gap and highlights it under Authorization and Property Authorization checks. The scanner also exercises the endpoint with sequential probes to see whether identical payloads and headers yield the same outcome, which is indicative of a missing replay safeguard.

SSRF and unsafe consumption findings can further exacerbate replay risks if internal services propagate API keys in a way that allows an attacker to trigger internal replay paths. middleBrick tests for SSRF and inspects how endpoints consume inputs, ensuring that keys are not reflected or forwarded in a manner that enables chaining attacks. Because the tool runs without credentials, it evaluates the public surface only, yet it can still identify endpoints that accept repeated, identical requests protected only by API keys.

Api Keys-Specific Remediation in Fastapi — concrete code fixes

To mitigate replay attacks while continuing to use API keys in Fastapi, introduce per-request uniqueness and server-side validation so that captured requests cannot be reused. A common approach is to require a client-supplied nonce or timestamp combined with the API key, and to enforce server-side checks that reject duplicates or stale requests. The server must store or verify nonces within an acceptable time window and ensure that each request is processed only once.

Below is a concrete Fastapi example that uses an API key plus a timestamp and a server-side cache to prevent replays within a short interval. It demonstrates how to extract the key and nonce, verify the timestamp freshness, and store recently seen nonces to block duplicates. This pattern complements API key validation rather than replacing it, and it aligns with remediation guidance that middleBrick provides in its prioritized findings.

from fastapi import FastAPI, Header, HTTPException, Request
import time
from typing import Set

app = FastAPI()

# In production, use a distributed cache like Redis if you run multiple workers
seen_nonces: Set[str] = set()
CACHE_TTL_SECONDS = 300  # 5 minutes; adjust based on request frequency
MAX_TIME_SKEW_SECONDS = 60  # allow clients to be slightly out of sync

@app.middleware("http")
async def reject_replayed_requests(request: Request, call_next):
    # Apply selectively to endpoints that require replay protection
    response = await call_next(request)
    return response

def is_timestamp_fresh(client_timestamp: float) -> bool:
    current = time.time()
    return abs(current - client_timestamp) <= MAX_TIME_SKEW_SECONDS

def register_nonce(nonce: str) -> bool:
    if nonce in seen_nonces:
        return False
    seen_nonces.add(nonce)
    # In real code, prune expired nonces periodically or use a TTL cache
    return True

@app.post("/transfer")
async def transfer(
    request: Request,
    api_key: str = Header(..., description="API key for authentication"),
    nonce: str = Header(..., description="Unique request identifier"),
    timestamp: float = Header(..., description="Unix timestamp in seconds"),
    amount: int = ...,
    target: str = ...
):
    # Validate API key (simplified; use a secure constant-time comparison and a store)
    valid_key = validate_api_key(api_key)
    if not valid_key:
        raise HTTPException(status_code=401, detail="Invalid API key")

    if not is_timestamp_fresh(timestamp):
        raise HTTPException(status_code=400, detail="Stale timestamp; possible replay")

    if not register_nonce(nonce):
        raise HTTPException(status_code=400, detail="Duplicate request detected; possible replay")

    # Process the transfer (placeholder)
    return {"status": "ok", "amount": amount, "target": target}

def validate_api_key(api_key: str) -> bool:
    # Replace with secure lookup and constant-time comparison
    allowed_keys = {"s3cr3t_k3y_ex4mpl3"}
    return api_key in allowed_keys

This example illustrates that API key validation alone is insufficient; you must couple the key with a nonce or timestamp and enforce freshness and uniqueness on the server. middleBrick’s findings can highlight the absence of such protections even when API keys are present, and its remediation guidance often recommends adding these per-request safeguards.

In addition to code changes, operational practices matter. Rotate API keys periodically, avoid logging full headers that contain keys, and enforce TLS to prevent on-path eavesdropping that enables replay. If your API exposes an OpenAPI spec, ensure that security schemes reflect the required headers and that servers validate constraints consistently. middleBrick’s dashboard can help you track these improvements over time by rescoring after fixes and showing per-category breakdowns.

Frequently Asked Questions

Can a replay attack happen even when API keys are rotated regularly?
Yes. If a captured request with a valid API key is replayed before the key is rotated and the server does not enforce nonce or timestamp checks, the replay can still succeed. Regular rotation reduces the window of exposure but does not eliminate the need for per-request replay protections.
Does middleBrick attempt to replay requests during scans?
middleBrick tests the unauthenticated attack surface and observes whether identical requests produce the same outcome, which helps identify missing replay protections. It does not perform active replay exploitation; it reports findings and provides remediation guidance.