HIGH replay attackfastapidynamodb

Replay Attack in Fastapi with Dynamodb

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

A replay attack occurs when an attacker intercepts a valid request and re-sends it to the API to achieve unauthorized access or perform an action multiple times. In a Fastapi application that uses Amazon DynamoDB as the primary data store, this risk is shaped by three dimensions: the HTTP layer (Fastapi), the database layer (DynamoDB), and the absence of protective mechanisms that middleBrick checks as part of its unauthenticated, black-box scan.

Fastapi does not prevent replay by default. If endpoints accept mutable state-changing requests (POST, PUT, PATCH) without idempotency controls, an intercepted request can be replayed with the same or slightly altered parameters. For example, a payment or resource creation endpoint that relies only on authentication tokens or API keys can be vulnerable when those tokens are reused across requests. DynamoDB itself does not provide built-in replay protection; it stores whatever data is written. If the application uses natural keys (e.g., user ID + timestamp) without enforcing uniqueness constraints, replayed writes can result in duplicate records or unintended updates. MiddleBrick scans for missing idempotency safeguards, missing request nonces or timestamps, and weak rate limiting, surfacing these as Authentication, BOLA/IDOR, and Input Validation findings.

DynamoDB-specific factors amplify the exposure. When requests lack a client-generated idempotency token and the application uses a simple conditional write (e.g., checking a unique request_id attribute), race conditions can allow two near-simultaneous replays to both pass the condition before the first write is visible. Additionally, if responses include sensitive data (such as keys or PII) and are not encrypted in transit or at rest, a captured response can be reused to infer context or to perform credential stuffing. MiddleBrick’s checks for Data Exposure and Encryption highlight whether responses leak data and whether the API enforces TLS, while its checks for Rate Limiting and Unsafe Consumption surface missing request throttling that would otherwise hinder replay attempts.

An example vulnerable pattern is an endpoint that creates a DynamoDB item using a client-supplied identifier without verifying freshness or uniqueness:

import boto3
from fastapi import FastAPI, HTTPException

app = FastAPI()
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('requests')

@app.post('/submit')
def submit(request_id: str, user_id: str, payload: dict):
    # Vulnerable: no idempotency token verification, no timestamp/nonce check
    response = table.put_item(Item={'request_id': request_id, 'user_id': user_id, 'payload': payload})
    return {'status': 'accepted'}

In this pattern, an attacker who captures request_id, user_id, and payload can replay the call with the same parameters. DynamoDB will accept the write unless conditional checks prevent duplicates. MiddleBrick would flag missing idempotency handling and insufficient input validation as actionable findings, with remediation guidance to introduce uniqueness constraints and cryptographic nonces.

Dynamodb-Specific Remediation in Fastapi — concrete code fixes

To mitigate replay attacks in Fastapi with DynamoDB, implement idempotency at the application layer, enforce uniqueness, and validate temporal freshness. Below are concrete, DynamoDB-aware code patterns that align with the checks middleBrick performs and the remediation guidance it provides.

  • Use a client-provided idempotency key with a uniqueness constraint in DynamoDB. Store the key with a TTL so that old keys expire and storage does not grow indefinitely.
  • Add a server-side nonce or timestamp window to reject stale requests. Verify that timestamps are within an acceptable skew (for example, ±2 minutes) and that nonces have not been used before for the same entity.
  • Employ conditional writes to ensure that duplicate keys cannot overwrite existing valid data, and return a clear conflict response instead of silently succeeding.
  • Enforce TLS and avoid returning sensitive data in responses that could be reused; use environment-managed credentials and avoid embedding secrets in code.

Secure implementation example:

import boto3
from fastapi import FastAPI, HTTPException
from datetime import datetime, timezone
import time

app = FastAPI()
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('requests')

# Idempotency TTL in seconds (e.g., 24 hours)
IDEMPOTENCY_TTL = 86400
# Allowed clock skew in seconds
CLOCK_SKEW = 120

def is_fresh(timestamp: float) -> bool:
    return abs(datetime.now(timezone.utc).timestamp() - timestamp) <= CLOCK_SKEW

@app.post('/submit')
def submit(
    idempotency_key: str,
    request_ts: float,
    user_id: str,
    payload: dict
):
    # Reject requests with stale timestamps
    if not is_fresh(request_ts):
        raise HTTPException(status_code=400, detail='Request timestamp too old or in the future')

    # Conditional write to enforce uniqueness of idempotency key
    try:
        table.put_item(
            Item={
                'idempotency_key': idempotency_key,
                'user_id': user_id,
                'payload': payload,
                'request_ts': request_ts,
                'ttl': int(time.time()) + IDEMPOTENCY_TTL
            },
            ConditionExpression='attribute_not_exists(idempotency_key)'
        )
    except Exception as e:
        # A ConditionalCheckFailedException indicates a duplicate replay
        if e.response.get('Error', {}).get('Code') == 'ConditionalCheckFailedException':
            raise HTTPException(status_code=409, detail='Duplicate request detected')
        raise

    return {'status': 'accepted', 'idempotency_key': idempotency_key}

This pattern ensures that each idempotency_key can be written only once (conditional write), and that old keys eventually expire via TTL. The timestamp check defends against replays using captured requests that are slightly delayed. MiddleBrick’s scans highlight missing idempotency and timestamp validation; applying these fixes addresses the findings and improves the security risk score across Authentication, Input Validation, and Data Exposure checks.

Additionally, ensure that all communication with DynamoDB occurs over TLS and that responses do not leak sensitive information. MiddleBrick’s Encryption and Data Exposure checks can help verify that the API meets baseline transport and output safety expectations. For ongoing protection, use the Pro plan’s continuous monitoring to detect new anomalies and integrate the GitHub Action to fail builds if a future change weakens idempotency or validation.

Frequently Asked Questions

Can a replay attack succeed if I use HTTPS only?
HTTPS protects data in transit but does not prevent replay. An attacker can still capture and re-send a valid request. You must implement idempotency, nonces, or timestamps to stop replays.
Does DynamoDB protect against replays automatically?
No. DynamoDB stores requests as written; it does not detect duplicate intents. You must enforce uniqueness in your application layer via conditional writes and idempotency keys.