HIGH ssrffastapihmac signatures

Ssrf in Fastapi with Hmac Signatures

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

Server-Side Request Forgery (SSRF) in FastAPI applications that use HMAC signatures for request authentication can occur when the application uses the HMAC to verify integrity or origin but does not adequately validate the target URL before using it in a backend request. In this pattern, the client computes an HMAC over a URL or set of parameters and sends it alongside the request. The server recomputes the HMAC and, if it matches, forwards the request to the provided URL. The vulnerability arises when the server trusts the HMAC check alone and does not enforce strict URL allowlists or parsing rules before performing the outbound call.

An attacker can supply a URL that the HMAC validates (due to a weak key or predictable input) but that points to internal services such as http://127.0.0.1:8000/admin, cloud metadata endpoints like http://169.254.169.254/latest/meta-data/, or internal Kubernetes services like http://kubernetes.default.svc. Because the HMAC is intended to ensure authenticity, developers may skip additional validation, assuming that only a legitimate client could produce a valid signature. However, if the HMAC key is leaked or the signature algorithm is misconfigured, or if the server-side code does not canonicalize the URL, an attacker can induce the server to make arbitrary internal requests.

In FastAPI, this can manifest when an endpoint accepts a URL parameter, a JSON body field, or a query string that specifies a target, then uses an HMAC to validate some property of that input. If the server deserializes the input, verifies the HMAC, and then uses an HTTP client (e.g., httpx or requests) to call the provided URL without ensuring it is external and safe, the SSRF vector is live. The attack may be used to scan internal networks, reach metadata services, or pivot to other internal protocols. Even with HMAC integrity, confidentiality and availability risks remain because the server acts as a proxy to internal endpoints.

OpenAPI/Swagger analysis can highlight endpoints that accept free-form URLs, but without runtime validation rules, the spec does not prevent unsafe resolution of $ref paths or improper input handling. middleBrick scans such configurations and flags SSRF risks when outbound calls are made to unchecked targets, even when HMAC verification is present, because the scan tests the unauthenticated attack surface and observes actual request behavior.

Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes

To remediate SSRF in FastAPI when HMAC signatures are used, treat the HMAC as integrity-only and enforce strict URL validation before any outbound request. Do not rely on the signature to imply safety. Use an allowlist of permitted hosts or schemes, canonicalize the URL, and avoid forwarding requests to internal or sensitive targets.

Example secure FastAPI implementation with HMAC verification and URL allowlisting:

import hmac
import hashlib
from urllib.parse import urlparse
from fastapi import FastAPI, HTTPException, Header
import httpx

app = FastAPI()

ALLOWED_HOSTS = {"api.external.com", "data.example.org"}
SECRET_KEY = b"super-secret-key"

def verify_hmac(payload: str, signature: str) -> bool:
    computed = hmac.new(SECRET_KEY, payload.encode("utf-8"), hashlib.sha256).hexdigest()
    return hmac.compare_digest(computed, signature)

def is_allowed_url(url: str) -> bool:
    parsed = urlparse(url)
    return parsed.hostname in ALLOWED_HOSTS and parsed.scheme in {"https"}

@app.post("/fetch")
async def fetch_resource(url: str, signature: str = Header(...)):
    payload = url  # in practice, this should be the exact string signed by the client
    if not verify_hmac(payload, signature):
        raise HTTPException(status_code=401, detail="Invalid signature")
    if not is_allowed_url(url):
        raise HTTPException(status_code=400, detail="URL not allowed")
    async with httpx.AsyncClient() as client:
        response = await client.get(url, timeout=10.0)
        response.raise_for_status()
        return {"content": response.text[:500]}

Key practices include canonicalizing the URL (e.g., lowercasing the host, removing default ports), rejecting URLs with usernames/passwords or embedded credentials, and blocking private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and loopback addresses. You can integrate these checks into your FastAPI routes and use the CLI tool (middlebrick scan <url>) to validate that endpoints accepting external URLs are flagged and remediated. For teams using CI/CD, the GitHub Action can enforce thresholds so that builds fail if risky URL handling patterns are detected in staging environments.

Additionally, prefer indirect references (e.g., internal IDs mapped to vetted URLs on the server) rather than forwarding user-supplied URLs. If you must forward, use a strict allowlist and monitor outbound traffic. The MCP Server can help scan API definitions and generated client code in your IDE to catch missing validations early.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

Can HMAC signatures alone prevent SSRF in FastAPI?
No. HMAC signatures provide integrity and authenticity but do not restrict where a request can be sent. Always validate and restrict target URLs with allowlists before making outbound calls.
What should I allowlist to mitigate SSRF in FastAPI with HMAC?
Allowlist specific hostnames and schemes (e.g., https://api.external.com), reject private IPs and loopback addresses, and avoid forwarding to user-supplied paths or ports.