Beast Attack in Fastapi with Hmac Signatures
Beast Attack in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
A Beast Attack in the context of FastAPI with HMAC signatures occurs when an attacker can observe and manipulate authenticated messages in a way that reveals information about the plaintext or authentication state. This typically arises when HMAC is used to sign requests but the application does not enforce strict validation of message integrity before processing business logic. FastAPI applications that rely on HMAC for request authentication are at risk if the signature verification is performed after deserialization or after partial processing of the payload, allowing an attacker to submit modified but still verifiable messages and infer properties of valid data.
Consider a FastAPI endpoint that accepts JSON payloads and uses an HMAC-SHA256 signature in a header to authenticate requests. If the server computes the HMAC over the raw request body but then deserializes the JSON into a Pydantic model before verifying the signature, an attacker can intercept and modify the serialized JSON. Because the server may expose information through error messages, timing differences, or behavior changes based on field values, the attacker can perform a bit-flipping or padding-based attack to learn about valid signatures or infer properties of other users’ data. This aligns with the broader BOLA/IDOR and Input Validation checks in middleBrick’s 12 security checks, where improper ordering of validation and authentication enables information leakage.
In a real-world scenario, an attacker might send a request with a modified user identifier while keeping the HMAC valid by exploiting predictable structure or weak key management. If the FastAPI application returns different HTTP status codes or response bodies depending on whether the deserialized object passes internal business rules, the attacker can distinguish between valid and invalid payloads without knowing the HMAC key. This violates the principle that authentication and integrity checks must precede any side-effectful processing. middleBrick’s scan would flag this as a high-severity finding under BOLA/IDOR and Input Validation, highlighting the need to verify signatures before deserialization and to ensure uniform error handling.
Additionally, if the HMAC implementation uses a static or predictable key, or if the same key is reused across multiple endpoints with different security requirements, the attack surface expands. An attacker who compromises one endpoint or gains access to logs containing signed payloads may attempt to recover the key or forge messages for other endpoints. The LLM/AI Security checks in middleBrick specifically test for system prompt leakage and prompt injection, but they also emphasize that any endpoint handling authenticated requests must ensure that HMAC verification is robust, keys are rotated, and no auxiliary data is leaked through error messages or timing channels.
To illustrate, a vulnerable FastAPI route might look like this in practice, where the signature is verified after model parsing, creating an opportunity for an attacker to manipulate the request before verification:
from fastapi import FastAPI, Header, HTTPException
import hmac
import hashlib
import json
from pydantic import BaseModel
app = FastAPI()
SECRET_KEY = b"static-key-2023"
class Item(BaseModel):
item_id: int
value: str
def verify_hmac(body: bytes, received_sig: str) -> bool:
computed = hmac.new(SECRET_KEY, body, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, received_sig)
@app.post("/items/")
async def create_item(item: Item, x_signature: str = Header(...)):
# Vulnerable: body is already consumed and parsed before verification
# In practice, FastAPI reads the body once; this example assumes raw access
raw_body = ??? # Not straightforward in FastAPI, encouraging misuse
if not verify_hmac(raw_body, x_signature):
raise HTTPException(status_code=401, detail="Invalid signature")
# Process item
return {"status": "ok"}
In this pattern, if the raw body is not captured correctly—FastAPI’s dependency system may have already read the stream—the verification may be incomplete or inconsistent. An attacker could exploit this inconsistency to submit crafted requests that pass verification under certain conditions, especially if the application does not enforce strict canonicalization of the JSON payload before signing.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To mitigate Beast Attack risks in FastAPI with HMAC signatures, ensure that signature verification occurs before any deserialization or business logic, using the raw request body exactly as received. FastAPI does not natively expose the raw body in the path operation function after parsing, so you must use a dependency or middleware to capture and verify the signature early. The following approach uses a dependency that reads the raw body, verifies the HMAC, and only then constructs the Pydantic model.
Use Request to access the raw body and perform verification before model binding:
from fastapi import FastAPI, Request, Depends, HTTPException
import hmac
import hashlib
import json
from pydantic import BaseModel
app = FastAPI()
SECRET_KEY = b"secure-rotating-key"
class Item(BaseModel):
item_id: int
value: str
def verify_hmac(body: bytes, received_sig: str) -> bool:
computed = hmac.new(SECRET_KEY, body, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, received_sig)
def get_verified_item(request: Request):
raw_body = request.body()
signature = request.headers.get("x-signature")
if not signature or not verify_hmac(raw_body, signature):
raise HTTPException(status_code=401, detail="Invalid signature")
# Only after verification, parse the body
return json.loads(raw_body)
@app.post("/items/")
async def create_item(data: dict = Depends(get_verified_item)):
item = Item(**data)
return {"status": "ok", "item_id": item.item_id}
This pattern ensures that the HMAC is computed over the exact byte sequence sent by the client, avoiding issues with FastAPI’s internal body consumption. It also enforces that any modification to the payload invalidates the signature, preventing bit-flipping attacks. The use of hmac.compare_digest mitigates timing attacks on signature comparison.
Additionally, rotate keys periodically and avoid static keys in production. While middleBrick’s Free plan allows quick scans to detect such misconfigurations, the Pro plan provides continuous monitoring to alert you if endpoints begin accepting requests with weak or predictable HMAC usage. The GitHub Action can be configured to fail builds if risk scores degrade due to authentication weaknesses.
For completeness, here is an example of a robust HMAC verification dependency that integrates with FastAPI’s dependency injection system and ensures canonical JSON serialization before signing, reducing the risk of encoding-based bypasses:
import orjson
from fastapi import Request, Depends, HTTPException
import hmac
import hashlib
SECRET_KEY = b"dynamic-key-2024"
def verify_hmac_strict(request: Request):
raw_body = request.body()
if not raw_body:
raise HTTPException(status_code=400, detail="Empty body")
signature = request.headers.get("x-signature")
if not signature:
raise HTTPException(status_code=401, detail="Missing signature")
# Ensure canonical representation if re-serializing (not needed when verifying raw)
if not hmac.compare_digest(
hmac.new(SECRET_KEY, raw_body, hashlib.sha256).hexdigest(),
signature
):
raise HTTPException(status_code=401, detail="Invalid signature")
return orjson.loads(raw_body)
By applying these Hmac Signatures-specific remediation steps, FastAPI applications can effectively neutralize Beast Attack vectors that exploit timing, deserialization order, or weak key management. middleBrick’s scans will highlight the initial vulnerability, and the Pro plan’s continuous monitoring helps ensure that such patterns do not reappear after code changes.
Frequently Asked Questions
Why does verifying HMAC after deserialization increase the risk of a Beast Attack in FastAPI?
How can I ensure my FastAPI HMAC verification is resistant to timing attacks?
hmac.compare_digest for signature comparison, and verify the HMAC using the raw request body before any deserialization or business logic. This ensures constant-time comparison and prevents attackers from gaining timing insights.