Security Misconfiguration in Fastapi with Hmac Signatures
Security Misconfiguration in Fastapi with Hmac Signatures
Security misconfiguration occurs when security controls are not defined, implemented, or maintained correctly. In Fastapi applications that use Hmac Signatures for request authentication, misconfiguration can undermine the integrity guarantees that Hmac is designed to provide.
Hmac relies on a shared secret and a deterministic algorithm to produce a signature that a server can verify. If the server-side verification logic diverges from the client-side construction—even subtly—an attacker can forge requests without knowing the secret. Common misconfigurations include using different hash algorithms between client and server, failing to enforce a canonical payload representation, not protecting against timing attacks during comparison, and incorrectly handling multiple signatures or key rotation.
In Fastapi, a typical misconfiguration risk arises when developers manually concatenate headers, query parameters, and body without a strict canonicalization policy. For example, including or excluding whitespace, using different newline conventions, or failing to sort query parameters can produce different byte sequences for semantically identical requests. This allows an attacker to modify non-signature-carrying parts of a request (such as metadata or idempotency keys) without invalidating the Hmac.
Another misconfiguration is using a weak or predictable secret stored in environment variables that are inadvertently exposed through logs, error pages, or container inspection. Fastapi applications that log raw requests may also leak signature material if developers inadvertently include signature headers in debug output. Additionally, accepting any hash algorithm negotiated via headers (e.g., allowing the client to specify the algorithm) can lead to downgrade attacks where an attacker forces use of a weaker hash like MD5 or SHA1.
Runtime differences between client and server environments can also introduce subtle bugs. For example, a client written in Python using hashlib.sha256 may produce a different byte representation of Unicode text than a server running Node.js, if encoding is not explicitly normalized (e.g., UTF-8). Such mismatches can cause valid signatures to fail verification, leading developers to relax checks in a way that weakens security.
Because middleBrick scans the unauthenticated attack surface and tests authentication and integrity controls among its 12 parallel checks, it can surface indicators of Hmac-related misconfiguration without needing credentials. The scanner examines input validation, authentication mechanisms, and property authorization to identify inconsistencies between documented expectations and runtime behavior.
Hmac Signatures-Specific Remediation in Fastapi
Remediation centers on implementing a strict, consistent Hmac construction and verification flow, using constant-time comparison, and hardening secrets and algorithms.
Client-side signing (canonicalization + Hmac)
import hmac
import hashlib
import json
from typing import Dict, Any
def build_hmac_signature(secret: str, method: str, path: str, timestamp: str, payload: Dict[str, Any]) -> str:
# Deterministic canonical JSON: sorted keys, no extra whitespace
body = json.dumps(payload, separators=(',', ':'), sort_keys=True)
# Canonical string: method, path, timestamp, body
message = f'{method}\n{path}\n{timestamp}\n{body}'
signature = hmac.new(
secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
Server-side verification in Fastapi
from fastapi import Fastapi, Request, HTTPException, Header
import hmac
import hashlib
import json
import time
app = Fastapi()
# Load secret securely (e.g., from a secrets manager in production)
HMAC_SECRET = "super-secure-secret"
@app.middleware("http")
async def verify_hmac_signature(request: Request, call_next):
# Only protect endpoints that require it
if request.url.path.startswith("/api/"):
timestamp = request.headers.get("x-request-timestamp")
signature_header = request.headers.get("x-signature-sha256")
if not timestamp or not signature_header:
raise HTTPException(status_code=400, detail="Missing signature headers")
# Prevent replay: allow a narrow time window (e.g., 5 minutes)
try:
req_time = int(timestamp)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid timestamp")
if abs(time.time() - req_time) > 300:
raise HTTPException(status_code=401, detail="Request expired")
# Read body exactly once; Fastapi's request.body() consumes the stream
body_bytes = await request.body()
# Reconstruct canonical message exactly as client did
method = request.method
path = request.url.path
# Important: use the raw body bytes, not re-parsed JSON
message = f'{method}\n{path}\n{timestamp}\n{body_bytes.decode("utf-8")}'
expected = hmac.new(
HMAC_SECRET.encode("utf-8"),
message.encode("utf-8"),
hashlib.sha256
).hexdigest()
# Constant-time comparison to avoid timing attacks
if not hmac.compare_digest(expected, signature_header):
raise HTTPException(status_code=401, detail="Invalid signature")
response = await call_next(request)
return response
Hardening measures
- Use a strong, randomly generated secret; rotate keys according to a defined schedule and maintain overlap during rotation.
- Always specify the hash algorithm (e.g., SHA-256); do not allow the client to negotiate the algorithm via headers.
- Normalize inputs to UTF-8 and enforce a canonical JSON serialization (sorted keys, no whitespace) on both sides.
- Use
hmac.compare_digestfor signature comparison to prevent timing attacks. - Validate and bound timestamps to mitigate replay attacks; reject requests with timestamps outside an acceptable window.
- Ensure secret storage is protected and not exposed in logs; avoid logging signature headers or full requests that include them.
- Document and test the canonicalization rules rigorously; small differences in serialization can break verification and lead to insecure relaxations.
By aligning client and server canonicalization, enforcing strict algorithm usage, and applying constant-time verification, the risk of Hmac misconfiguration in Fastapi is significantly reduced.