Ssrf in Django with Bearer Tokens
Ssrf in Django with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Server-Side Request Forgery (SSRF) in Django becomes particularly concerning when APIs use Bearer Tokens for authorization. In Django-based services that accept external URLs and make outbound HTTP requests, an attacker can supply a malicious URL that causes the server to reach internal endpoints or metadata services. If the Django application adds Bearer Tokens to those outbound requests—such as calling another service on behalf of the original caller or to reach a protected upstream API—those tokens may be inadvertently exposed or used in unintended contexts.
Consider a Django view that fetches a user-provided URL and forwards an Authorization header containing a Bearer Token. If input validation is weak and the application does not enforce strict allowlists, an attacker can supply an internal address like http://169.254.169.254/latest/meta-data/iam/security-credentials/ (AWS instance metadata). The Django process, executing with its own service identity, may include its Bearer Token when contacting the external or internal endpoint, effectively leaking credentials internally or to an external attacker-controlled callback if SSRF to a malicious listener is possible.
SSRF with Bearer Tokens also surfaces when Django proxies requests to backend APIs that themselves require token-based access. If an attacker can influence the target URL and the request includes a Bearer Token, the server may be tricked into interacting with internal services (e.g., http://internal-api:8000/admin), using the compromised token to escalate access or bypass intended network segmentation. The risk is amplified when token handling is naive—such as reusing a single token across outbound calls—because a single SSRF vector can expose multiple protected resources.
In practice, this often manifests in Django apps that consume OpenAPI specs and dynamically generate requests, or that integrate with third-party APIs where Bearer Tokens are stored in settings or short-lived credentials passed around in code. Even if the Django app does not directly leak the token, SSRF can allow an attacker to infer the presence of internal APIs and probe them using the forwarded authorization context, turning a seemingly harmless integration into an access escalation path.
middleBrick scans such scenarios as part of its 12 security checks, including Input Validation and SSRF, and can surface these risks even when scanning unauthenticated endpoints. By correlating OpenAPI/Swagger specs with runtime behavior, the scanner can identify places where Bearer Token usage intersects with user-controlled URL inputs, helping you recognize where SSRF could lead to token exposure or misuse.
Bearer Tokens-Specific Remediation in Django — concrete code fixes
To mitigate SSRF when Bearer Tokens are involved, enforce strict allowlisting of target hosts and disable automatic forwarding of Authorization headers to user-controlled destinations. Never pass incoming tokens directly to outbound requests without validation. Below are concrete patterns to implement in Django.
1. Validate and restrict outbound targets
Create a small validation utility that only permits known, safe domains or patterns. Do not rely on regex alone; combine host allowlists with optional path restrictions.
import requests
from urllib.parse import urlparse
from django.conf import settings
from django.core.exceptions import ValidationError
ALLOWED_HOSTS = {"api.example.com", "internal.example.com"}
def validate_url(value: str) -> str:
parsed = urlparse(value)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValidationError(f"Host not allowed: {parsed.hostname}")
if parsed.scheme not in {"https", "http"}:
raise ValidationError("Unsupported scheme")
return value
def fetch_external(url: str, token: str) -> requests.Response:
# validated before calling this function
headers = {"Authorization": f"Bearer {token}"}
return requests.get(url, headers=headers, timeout=5)
2. Do not forward incoming Bearer Tokens blindly
If your service receives a Bearer Token from a client and must call another API, avoid blindly reusing that token. Instead, use a server-side token or a scoped token with limited permissions. If you must forward, ensure the target is validated and the token is not sourced directly from user input.
import os
import requests
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
SERVER_SIDE_TOKEN = os.getenv("UPSTREAM_API_TOKEN") # stored securely
@require_http_methods(["GET"])
def proxy_to_upstream(request):
target = request.GET.get("url")
if not target:
return JsonResponse({"error": "url required"}, status=400)
# Validate target host strictly
validated = validate_url(target)
headers = {"Authorization": f"Bearer {SERVER_SIDE_TOKEN}"}
resp = requests.get(validated, headers=headers, timeout=5)
return JsonResponse(resp.json(), status=resp.status_code)
3. Use requests-safe session and disable redirects to untrusted hosts
Control redirect behavior to prevent open redirects or SSRF through chained URLs. Disable automatic handling of redirects to user-controlled locations.
import requests
def safe_request(url: str, token: str):
headers = {"Authorization": f"Bearer {token}"}
resp = requests.get(
url,
headers=headers,
allow_redirects=False,
timeout=5,
)
# manually inspect Location if needed, do not follow automatically
return resp
4. Apply defense-in-depth with network controls
Run Django workers in network-segmented environments where tokens are not routable to sensitive internal zones. Use firewall rules and service mesh policies to prevent outbound connections to metadata services (e.g., 169.254.169.254) from application containers.
middleBrick’s scans can validate these mitigations by checking input validation strictness and SSRF-related findings. Its OpenAPI-aware checks can highlight places where user-controlled URLs intersect with Authorization usage, supporting remediation aligned with OWASP API Top 10 and common compliance frameworks.
Related CWEs: ssrf
| CWE ID | Name | Severity |
|---|---|---|
| CWE-918 | Server-Side Request Forgery (SSRF) | CRITICAL |
| CWE-441 | Unintended Proxy or Intermediary (Confused Deputy) | HIGH |