GuardAPI Logo
GuardAPI

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>
System Alert • ID: 5604
Target: Django API
Potential Vulnerability

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.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

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.