Dns Rebinding in Django with Dynamodb
Dns Rebinding in Django with Dynamodb — how this specific combination creates or exposes the vulnerability
DNS rebinding is a client-side attack where an attacker tricks a victim’s browser into resolving a domain to an internal IP address, bypassing same-origin policies. In a Django application that interacts with DynamoDB, this can expose internal services or unsafe internal endpoints if the backend makes requests based on attacker-controlled input. For example, if your Django backend accepts a hostname or URL from the client and uses it to build a DynamoDB endpoint or a related service URL, an attacker-controlled DNS record can cause the request to target an internal AWS metadata service or a private DynamoDB proxy that is not intended for external access.
Consider a scenario where Django dynamically constructs a service endpoint using a user-supplied parameter that influences the hostname resolved for DynamoDB operations. If the parameter is not strictly validated and is used to form a hostname, DNS rebinding can redirect the request to an internal address. Because the request originates from the Django server (or a runtime environment with AWS credentials), it may succeed against internal endpoints that would otherwise be unreachable. This can lead to unintended data access or exposure of internal AWS metadata, depending on how the AWS SDK is configured within Django.
With DynamoDB, the risk arises when the backend uses a flexible hostname configuration for the AWS SDK endpoint or when VPC endpoints and private DNS names are involved. If an attacker can cause the Django application to resolve a hostname to an AWS internal IP via rebinding, the SDK might inadvertently send requests to an unintended internal service. Although DynamoDB endpoints are typically fixed, custom endpoint configurations or use of AWS SDK features like endpoint_url increase the attack surface. The Django application must treat all external hostnames as untrusted, especially when they influence SDK client construction, to prevent DNS rebinding from reaching internal resources.
Dynamodb-Specific Remediation in Django — concrete code fixes
To mitigate DNS rebinding risks in Django when working with DynamoDB, enforce strict hostname validation and avoid using attacker-controlled input to construct AWS SDK endpoints. Prefer using the default AWS endpoint resolution and explicitly specify regions instead of dynamic hostnames. When you must customize the endpoint, validate the hostname against a strict allowlist and avoid resolving user input to internal IPs.
Example 1: Safe DynamoDB client initialization with region-based endpoint
import boto3
from django.conf import settings
def get_dynamodb_client():
# Use a fixed region from settings; do not derive endpoint from user input
region = getattr(settings, 'AWS_DEFAULT_REGION', 'us-east-1')
return boto3.client('dynamodb', region_name=region)
Example 2: Validating a custom hostname before use
from urllib.parse import urlparse
import socket
ALLOWED_HOSTS = {'dynamodb.us-east-1.amazonaws.com'}
def is_safe_hostname(hostname):
parsed = urlparse(hostname)
host = parsed.hostname or hostname
# Ensure hostname resolves to a public AWS endpoint only
try:
resolved = socket.gethostbyname(host)
# Reject private IPs
if resolved.startswith('10.') or resolved.startswith('192.168.') or resolved.startswith('172.16.'):
return False
except socket.error:
return False
return host in ALLOWED_HOSTS
def get_custom_dynamodb_client(custom_hostname):
if not is_safe_hostname(custom_hostname):
raise ValueError('Unsafe hostname')
return boto3.client('dynamodb', endpoint_url=f'https://{custom_hostname}')
Example 3: Using resource with explicit configuration
import boto3
from django.conf import settings
def get_dynamodb_resource():
region = getattr(settings, 'AWS_DEFAULT_REGION', 'us-east-1')
# Avoid passing endpoint_url derived from user input
return boto3.resource('dynamodb', region_name=region)
General Django middleware recommendations
- Validate and sanitize any hostnames or URLs used to configure AWS clients.
- Do not allow user input to directly set
endpoint_urlwithout strict allowlisting and IP rejection. - Use environment variables or secure settings for region and endpoint configuration.
- Monitor and log unexpected endpoint resolutions as part of runtime security.