Fix SSRF (Server Side Request Forgery) in Django
SSRF (Server-Side Request Forgery) in Django occurs when an application accepts a user-supplied URL and fetches it without proper validation. Attackers leverage this to pivot into internal networks, scan local ports, or exfiltrate sensitive cloud metadata (e.g., AWS/GCP instance credentials). A simple 'requests.get()' on raw input is a high-severity vulnerability.
The Vulnerable Pattern
import requests from django.http import HttpResponse
def fetch_external_resource(request): # CRITICAL VULNERABILITY: User-controlled URL is fetched directly target_url = request.GET.get(‘url’) response = requests.get(target_url) return HttpResponse(response.content, content_type=response.headers[‘Content-Type’])
The Secure Implementation
To kill SSRF, you must implement a multi-layered defense. First, enforce HTTPS to prevent protocol smuggling (gopher://, file://). Second, use a strict whitelist for domains; blacklisting IPs is insufficient due to DNS Rebinding. Third, resolve the hostname to an IP and verify it does not belong to reserved private ranges (RFC 1918) or cloud metadata services (169.254.169.254). Finally, disable redirects in your HTTP client to prevent attackers from bypassing your initial domain check with a 302 jump to an internal target.
import requests
import socket
from django.core.exceptions import PermissionDenied
from urllib.parse import urlparse
ALLOWED_DOMAINS = [‘api.trusted-partner.com’, ‘images.cdn.com’]
def secure_fetch(request):
url = request.GET.get(‘url’)
parsed = urlparse(url)
# 1. Scheme Validation
if parsed.scheme not in ['https']:
raise PermissionDenied('Insecure protocol')
# 2. Domain Whitelisting
if parsed.netloc not in ALLOWED_DOMAINS:
raise PermissionDenied('Unauthorized domain')
# 3. Prevent DNS Rebinding & Internal IP Access
try:
resolved_ip = socket.gethostbyname(parsed.hostname)
private_ranges = ['127.', '10.', '172.16.', '172.31.', '192.168.', '169.254.', '0.0.0.0']
if any(resolved_ip.startswith(prefix) for prefix in private_ranges):
raise PermissionDenied('Access to internal network is prohibited')
except socket.gaierror:
raise PermissionDenied('Invalid hostname')
# 4. Request hardening: No redirects, strict timeout
response = requests.get(url, allow_redirects=False, timeout=3.0)
return HttpResponse(response.content)</code></pre>
Your Django API
might be exposed to SSRF (Server Side Request Forgery)
74% of Django apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.