PYTHON

Implement Basic Server-Side Request Forgery (SSRF) Protection

Learn techniques to mitigate Server-Side Request Forgery (SSRF) attacks by validating URLs and restricting outgoing requests in Python.

import requests
from urllib.parse import urlparse

def is_safe_url(url):
    # Define a whitelist of allowed domains or IP ranges
    ALLOWED_DOMAINS = ['api.example.com', 'trusted-cdn.net']
    FORBIDDEN_IPS = ['127.0.0.1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] # Private networks

    try:
        parsed_url = urlparse(url)

        # 1. Check scheme (only http/https)
        if parsed_url.scheme not in ['http', 'https']:
            return False

        # 2. Check hostname against whitelist
        if parsed_url.hostname not in ALLOWED_DOMAINS:
            # Advanced: resolve hostname to IP and check against forbidden IPs
            import socket
            ip_address = socket.gethostbyname(parsed_url.hostname)
            # Simple check for private IPs (more robust check needed for CIDR ranges)
            if ip_address.startswith(('127.', '10.', '172.16.', '192.168.')):
                return False
            
            # For production, use a proper CIDR matching library or a comprehensive IP blacklist
            # Example: from ipaddress import ip_address, ip_network
            # if any(ip_address(ip_address) in ip_network(f_ip) for f_ip in FORBIDDEN_IPS):
            #    return False

        return True
    except Exception:
        return False

def fetch_external_resource(url):
    if not is_safe_url(url):
        print(f"Blocked potentially unsafe URL: {url}")
        return None
    
    try:
        response = requests.get(url, timeout=5) # Set a timeout
        response.raise_for_status() # Raise an exception for bad status codes
        return response.text
    except requests.exceptions.RequestException as e:
        print(f"Error fetching URL {url}: {e}")
        return None

# Example usage:
print(fetch_external_resource('http://api.example.com/data'))
print(fetch_external_resource('http://localhost/admin')) # Should be blocked
print(fetch_external_resource('file:///etc/passwd')) # Should be blocked
print(fetch_external_resource('https://malicious-site.com')) # Should be blocked if not whitelisted
How it works: This Python snippet demonstrates basic protection against Server-Side Request Forgery (SSRF) attacks. SSRF occurs when an attacker can trick a server-side application into making requests to an arbitrary domain of the attacker's choosing. The 'is_safe_url' function validates incoming URLs by: 1. Ensuring the scheme is 'http' or 'https'. 2. Whitelisting allowed hostnames (e.g., your own APIs or trusted third parties). 3. Performing a rudimentary check to prevent requests to private IP ranges (e.g., localhost, internal networks), which an attacker might use to access internal services. For production, more robust IP validation (e.g., using 'ipaddress' module for CIDR matching) is recommended. The 'fetch_external_resource' function then uses this validation before making any external HTTP requests, also adding a timeout to prevent denial-of-service.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs