Ssrf Server Side in Fastapi with Hmac Signatures
Ssrf Server Side in Fastapi with Hmac Signatures — how this combination creates or exposes the vulnerability
Server-side request forgery (SSRF) in FastAPI applications that use HMAC signatures for request authentication can arise when a server-side component makes outbound HTTP calls to user-controlled URLs while also relying on HMAC-based schemes to validate integrity. The vulnerability is not in the HMAC verification itself, but in how the application resolves and forwards requests before verification or in how it handles URL inputs that bypass intended origin checks.
Consider a FastAPI endpoint that accepts a URL parameter, fetches resources from that URL on the server side, and then validates an HMAC included in headers or query parameters to ensure the request originates from a trusted source. If the server does not strictly validate the target host and allows internal network destinations, an attacker can supply a URL pointing to metadata services (e.g., http://169.254.169.254 for cloud instance metadata) or internal services that are not exposed publicly. Even when an HMAC is used elsewhere to authenticate client-to-server calls, a server-side SSRF path can circumvent client authentication entirely because the request originates from the backend, not the client.
HMAC signatures can inadvertently contribute to a false sense of security. For example, a developer may verify the HMAC to confirm that a request was not tampered with, but if the backend then uses a different HTTP client to call another service using a URL derived from the request (such as a redirect target or a webhook URL), the backend may resolve internal hostnames or follow redirects to internal endpoints. This can lead to SSRF via open redirects, template injection in URL construction, or SSRF through batch operations that iterate over user-supplied identifiers that map to internal addresses.
Real-world attack patterns include probing for metadata endpoints, exploiting internal DNS names, and leveraging SSRF to scan internal networks behind firewalls. In FastAPI, if URL construction uses string formatting or concatenation without strict validation, patterns such as {scheme}://{user_host}/path can be abused if user_host is not canonicalized and validated against a denylist or allowlist. Even when HMAC signatures protect the API contract, SSRF can still occur if the server trusts internal resolution of certain hostname patterns or fails to reject private IP ranges (RFC 1918) and loopback addresses.
middleBrick scans such endpoints among its 12 security checks, testing unauthenticated attack surfaces including input validation and data exposure paths. The scanner can surface SSRF risks in FastAPI services that perform server-side fetches, helping developers identify dangerous host resolution and redirect behaviors before they are exploited.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To remediate SSRF in FastAPI when HMAC signatures are in use, enforce strict URL validation before any server-side network call, canonicalize inputs, and avoid using user-controlled data to construct targets for outbound requests. Below are concrete code examples demonstrating secure patterns.
1. Validate and restrict target hosts
Use an allowlist of permitted hosts and reject private IP ranges. Do not rely solely on HMAC to prevent SSRF; treat HMAC as integrity protection for the request, not as a network boundary control.
from fastapi import FastAPI, Header, HTTPException
from urllib.parse import urlparse
import ipaddress
ALLOWED_HOSTS = {"api.external.com", "data.provider.com"}
app = FastAPI()
def is_private_url(url: str) -> bool:
parsed = urlparse(url)
try:
resolved = ipaddress.ip_address(parsed.hostname or "")
return resolved.is_private
except (ValueError, AttributeError):
return False
@app.get("/fetch-external")
def fetch_external(url: str, x_signature: str = Header(...)):
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_HOSTS:
raise HTTPException(status_code=400, detail="Host not allowed")
if is_private_url(url):
raise HTTPException(status_code=400, detail="Private URL not permitted")
# Assume verify_hmac is a function that validates the signature
if not verify_hmac(url, x_signature):
raise HTTPException(status_code=401, detail="Invalid signature")
# Perform the fetch using a trusted HTTP client; ensure client does not follow internal redirects unexpectedly
# ...
return {"status": "ok"}
2. Use a safe HTTP client and disable risky redirect behavior
When making outbound calls, disable automatic redirects and avoid passing user-controlled URLs directly to libraries that may follow internal network paths.
import httpx
client = httpx.Client(follow_redirects=False)
# Later in your handler
try:
response = client.get(target_url, timeout=10.0)
except httpx.TimeoutException:
raise HTTPException(status_code=504, detail="Upstream timeout")
3. Avoid dynamic URL assembly from user input
Do not build URLs using simple string interpolation. If you must construct URLs, use a URL parsing library and validate each component.
from pydantic import AnyUrl
def build_safe_url(base: str, path: str) -> str:
# Ensure base is a validated URL and path is a safe relative path
safe_base = AnyUrl.validate(base)
# Further checks can be applied to path segments
return f"{safe_base.rstrip('/')}/{path.lstrip('/')}"
middleBrick’s OpenAPI/Swagger spec analysis can help identify endpoints that perform server-side fetches by inspecting operation parameters and request bodies. When combined with runtime testing, this supports more accurate detection of SSRF risks in FastAPI services that use HMAC signatures.