Time Of Check Time Of Use in Fastapi with Hmac Signatures
Time Of Check Time Of Use in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Time Of Check Time Of Use (TOCTOU) is a class of race condition where the outcome of a security decision depends on the timing between a check and a subsequent use. In Fastapi, combining request signature verification (for example, Hmac Signatures) with resource state checks can introduce TOCTOU if the data used to validate the signature is read once, and later operations act on a potentially changed state without re-verifying integrity.
Consider a scenario where a client sends a request containing an identifier and an Hmac-signed payload. The server verifies the signature to ensure authenticity, then checks business rules (e.g., whether the resource exists or whether the user is authorized). If between the signature verification and the use of the resource (such as updating or deleting), the resource changes in a way the signature does not cover, an attacker can exploit the window to perform unauthorized actions. For example, an attacker might swap a resource identifier after a valid signature is obtained, or mutate state that the signature does not bind tightly to the operation, effectively bypassing authorization that was assumed to be enforced by the signature check.
Hmac Signatures protect integrity and authenticity of the signed data, but they do not inherently prevent TOCTOU if the server’s logic separates verification from state validation. Attack patterns include swapping identifiers, modifying mutable fields used in authorization decisions, or leveraging concurrent requests to race between check and use. Since Hmac Signatures in Fastapi are often computed over selected headers, path parameters, and body fields, any mismatch between what is signed and what is later used can lead to security gaps. This is especially relevant when Fastapi endpoints rely on cached or database state that can be altered by other requests between verification and action.
To illustrate, imagine a Fastapi endpoint that accepts an Hmac signature over a JSON body and an identifier. The server verifies the signature, confirms the identifier refers to a resource, and then performs an update. If the identifier is mutable and can be changed by another request after signature verification, the operation may act on a different resource than intended. The signature remains valid because it was computed over the original data, but the use phase operates on altered context, violating the intended security boundary.
In summary, TOCTOU with Hmac Signatures in Fastapi emerges when the integrity check does not tightly bind the entire execution context, allowing an attacker to manipulate state between verification and use. Defenses must ensure that the data covered by the Hmac includes all relevant state used in subsequent operations, or that state is re-validated within the same critical section without introducing race conditions.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
Remediation centers on ensuring that the data used for authorization and business logic is covered by the Hmac and verified immediately before use, minimizing the window between check and use. Below are concrete code examples for a Fastapi endpoint that uses Hmac Signatures and avoids TOCTOU by binding signature coverage to the operation.
First, a utility to compute and verify Hmac using SHA256:
import hmac
import hashlib
def compute_hmac(key: bytes, message: str) -> str:
return hmac.new(key, message.encode('utf-8'), hashlib.sha256).hexdigest()
def verify_hmac(key: bytes, message: str, signature: str) -> bool:
expected = compute_hmac(key, message)
return hmac.compare_digest(expected, signature)
Second, a Fastapi endpoint that includes the identifier inside the signed payload and recomputes authorization based on the signed data immediately before performing the action, avoiding reliance on mutable external state between check and use:
from fastapi import Fastapi, HTTPException, Depends, Header
import json
app = Fastapi()
SECRET_KEY = b'example-secret-key'
def get_payload_body(body: dict) -> str:
# Deterministic serialization to avoid signature mismatch
return json.dumps(body, sort_keys=True, separators=(',', ':'))
@app.post('/transfer')
def transfer_funds(
x_signature: str = Header(..., alias='X-Signature'),
body: dict
):
payload = get_payload_body(body)
if not verify_hmac(SECRET_KEY, payload, x_signature):
raise HTTPException(status_code=401, detail='Invalid signature')
# Use data directly from the signed payload; avoid extra lookups that can change
account_from = body.get('from')
account_to = body.get('to')
amount = body.get('amount')
# Ensure business rules are enforced on the signed data
if not account_from or not account_to or amount is None or amount <= 0:
raise HTTPException(status_code=400, detail='Invalid transfer data')
# Perform the operation immediately using the verified, signed inputs
# (In a real system, this would interact with a ledger under concurrency control)
return {'status': 'ok', 'signed_payload': payload}
Third, for operations that must reference server-side state, recompute authorization using the signed identifier and current server-side record within the same transaction or lock scope to prevent race conditions:
from fastapi import Fastapi, HTTPException, Header, Depends
import hashlib
def get_resource_id_from_signed_token(signature: str, secret: bytes) -> str:
# Assume token is the resource identifier signed directly
# Verification logic here; in practice use verify_hmac
return 'resource_id_from_verified_token'
@app.delete('/resource/{resource_id}')
def delete_resource(
resource_id: str,
x_signature: str = Header(...),
):
verified_id = get_resource_id_from_signed_token(x_signature, SECRET_KEY)
if verified_id != resource_id:
raise HTTPException(status_code=403, detail='Resource ID mismatch')
# Immediately use resource_id within a concurrency-safe context
# (e.g., database row-level lock or transaction)
return {'status': 'deleted'}
Key practices to mitigate TOCTOU with Hmac Signatures in Fastapi:
- Include all identifiers and mutable attributes used in authorization inside the signed payload.
- Perform authorization checks immediately after signature verification using only the signed data, avoiding additional lookups that can change.
- If server-side state must be consulted, ensure the check and use occur within a consistent concurrency control mechanism (e.g., transactions or locks) and that the signature covers the relevant keys.
- Use canonical serialization to prevent signature bypass due to formatting differences.