HIGH insecure designfastapihmac signatures

Insecure Design in Fastapi with Hmac Signatures

Insecure Design in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Insecure design in FastAPI when using HMAC signatures often arises from decisions that weaken integrity checks or key management rather than from a cryptographic flaw in HMAC itself. A common pattern is to compute the HMAC over only part of the request, such as the request body, while omitting critical elements like timestamps, nonces, or HTTP method and path. This incompleteness enables replay attacks because an attacker can reuse a valid signature with the same body on a different resource or at a later time.

Another insecure design choice is accepting any timestamp or nonce without reasonable bounds, which undermines replay protection. If the server does not enforce a tight clock skew window or a short validity period, an attacker can capture a signed request and replay it within the allowed window. Similarly, using a weak or shared secret across multiple services or tenants allows a compromise in one context to affect others, violating isolation principles.

Routing and parameter handling can also introduce design weaknesses. For example, if the signature is computed over a serialized representation that does not canonicalize parameter ordering, different serialization libraries or frameworks may produce semantically equivalent but byte-different representations, leading to signature mismatch or bypass. In addition, failing to validate the Content-Type header consistently can cause the server to compute the HMAC over a different byte representation than the client, resulting in either false rejections or acceptance of altered content.

Design omissions around error handling and logging can further weaken security. Revealing whether a signature mismatch was due to a bad signature versus a missing signature can aid attackers in refining tampering attempts. Lack of structured audit trails makes it harder to detect abuse patterns, such as repeated replays against a single endpoint.

These issues are detectable by middleBrick’s 12 security checks, including Input Validation and Authentication, which analyze request surface and signature validation logic. The LLM/AI Security checks additionally probe for unsafe API exposure that could allow unauthenticated usage of endpoints that should be protected by HMAC. By combining specification analysis with runtime testing, middleBrick maps findings to frameworks such as OWASP API Top 10 and provides prioritized remediation guidance rather than attempting to fix the implementation directly.

Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes

To remediate insecure design issues with HMAC signatures in FastAPI, use a canonical representation that includes HTTP method, request path, selected headers, and a timestamp with a short validity window. Below are concrete, working examples that demonstrate a secure approach.

Server-side signature verification with replay protection

The server computes the expected HMAC over a canonical string and checks it within a tight time window. It also maintains a short-lived cache of recently seen nonces to prevent reuse.

import time
import hmac
import hashlib
from fastapi import FastAPI, Request, HTTPException, Header
from typing import Dict

app = FastAPI()

# In production, use a distributed cache with TTL
seen_nonces: Dict[str, float] = {}
NONCE_TTL = 30  # seconds
MAX_CLOCK_SKEW = 5  # seconds

def verify_hmac(
    method: str,
    path: str,
    timestamp: str,
    nonce: str,
    body: bytes,
    signature_header: str,
    secret: bytes
) -> bool:
    # Replay protection: reject reused nonces
    now = time.time()
    if nonce in seen_nonces:
        if now - seen_nonces[nonce] < NONCE_TTL:
            return False
    # Reject old timestamps to limit replay window
    try:
        req_time = float(timestamp)
    except ValueError:
        return False
    if abs(now - req_time) > MAX_CLOCK_SKEW:
        return False
    # Canonical string: method|path|timestamp|nonce|body
    payload = f"{method.upper()}|{path}|{timestamp}|{nonce}|".encode() + body
    expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)

@app.post("/resource/{item_id}")
async def update_resource(
    item_id: str,
    request: Request,
    x_timestamp: str = Header(...),
    x_nonce: str = Header(...),
    x_signature: str = Header(...)
):
    secret = b"your-256-bit-secret"  # load securely in practice
    body = await request.body()
    if not verify_hmac(
        method=request.method,
        path=f"/resource/{item_id}",
        timestamp=x_timestamp,
        nonce=x_nonce,
        body=body,
        signature_header=x_signature,
        secret=secret
    ):
        raise HTTPException(status_code=401, detail="Invalid signature")
    # Process the request
    return {"status": "ok"}

Client-side signing example

The client constructs the same canonical string and includes the timestamp, nonce, and signature in headers.

import time
import hmac
import hashlib
import requests

def sign_request(method: str, path: str, body: bytes, secret: bytes):
    timestamp = str(int(time.time()))
    nonce = "unique-per-request-id"  # use a strong random or UUID in practice
    payload = f"{method.upper()}|{path}|{timestamp}|{nonce}|".encode() + body
    signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()
    headers = {
        "X-Timestamp": timestamp,
        "X-Nonce": nonce,
        "X-Signature": signature,
        "Content-Type": "application/json"
    }
    return headers, timestamp, nonce

# Example usage
secret = b"your-256-bit-secret"
headers, ts, nc = sign_request("POST", "/resource/123", b'{"name": "example"}', secret)
response = requests.post("http://localhost:8000/resource/123", json={"name": "example"}, headers=headers)

These examples emphasize canonicalization, strict replay protection via nonces, and bounded timestamp validity to address insecure design pitfalls. middleBrick’s scans can validate that such controls are present and consistently applied across endpoints.

Frequently Asked Questions

Does HMAC protect against tampering if the secret is weak or leaked?
No. HMAC guarantees integrity only as long as the secret remains confidential and has sufficient entropy. A weak or leaked secret allows an attacker to forge valid signatures, making server-side verification ineffective.
Can canonicalization differences between client and server cause false validation failures?
Yes. If the canonical string is not constructed identically on both sides (e.g., parameter ordering, encoding, or header inclusion), valid requests may be rejected. Standardize serialization and explicitly define the canonical format in your API specification.