Stack Overflow in Django with Mutual Tls
Stack Overflow in Django with Mutual TLS — how this specific combination creates or exposes the vulnerability
Stack Overflow attacks in Django with mutual TLS (mTLS) arise when an authenticated client sends many requests that require significant server-side processing or memory, and the TLS session remains open while the application is overloaded. In this setup, mTLS ensures strong client authentication via client certificates, but it does not limit how many concurrent requests an authenticated client can make. If Django or the underlying WSGI/uWSGI server does not enforce strict concurrency and resource limits, an attacker with a valid certificate can exhaust threads, file descriptors, or memory, causing service degradation or denial of service for other legitimate users.
The risk is compounded when mTLS is terminated at a load balancer or reverse proxy that does not enforce per-client connection and request rate limits. In such architectures, Django may see many completed TLS handshakes and authenticated requests, but lacks built-in mechanisms to throttle or queue excessive work from a single identity. This aligns with the BFLA/Privilege Escalation and Rate Limiting checks in middleBrick, which look for missing or weak controls that allow authenticated clients to consume disproportionate resources. Without explicit limits, a Stack Overflow–style overload can be triggered not by malformed input, but by legitimate but excessive request volume from a trusted client.
Moreover, if Django applications process large request bodies or perform expensive serialization/deserialization (e.g., nested JSON or XML) under mTLS, the combination of authenticated sessions and unbounded parsing can amplify memory usage. MiddleBrick’s checks for Input Validation and Unsafe Consumption are relevant here, as they assess whether the API properly constrains payload sizes and handles untrusted data safely even when the client presents a valid certificate. The scanner cross-references OpenAPI/Swagger 2.0/3.x definitions with runtime behavior to detect missing size constraints and missing throttling that can enable resource exhaustion in mTLS-protected endpoints.
Mutual TLS-Specific Remediation in Django — concrete code fixes
To mitigate Stack Overflow and resource exhaustion risks in Django with mutual TLS, apply rate limiting and request constraints at the points where mTLS authentication is verified. Below are concrete, working examples that integrate mTLS with Django middleware and configuration.
1. Configure Django to require and verify client certificates
Ensure your Django settings enforce client certificate verification and limit accepted TLS versions and ciphers. This does not by itself prevent overload, but it establishes a known baseline for authenticated clients.
import os
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
# Assume termination happens at a proxy; Django sees HTTPS
SECURE_SSL_REDIRECT = True
# If you terminate TLS at the app server, set these paths:
import ssl
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(
certfile=os.getenv('DJANGO_CERT_PATH', '/certs/server.crt'),
keyfile=os.getenv('DJANGO_KEY_PATH', '/certs/server.key'),
# For client verification:
cafile=os.getenv('DJANGO_CA_PATH', '/certs/ca.crt')
)
# Note: In production, offload TLS to a proxy/load balancer and rely on
# SECURE_PROXY_SSL_HEADER + request.META['SSL_CLIENT_VERIFY'] = 'SUCCESS'
2. Add mTLS-aware rate limiting using Django Ratelimit
Use a token-bucket or fixed-window strategy that considers the client certificate’s identity (e.g., the Common Name or Subject Alternative Name). This prevents a single authenticated client from exhausting resources.
from ratelimit.decorators import ratelimit
from django.http import JsonResponse
import ssl
def get_client_cert_id(request):
# When behind a proxy that sets SSL client cert fields:
cert = request.META.get('SSL_CLIENT_CERT')
if cert:
# Extract a stable identifier; in practice use a hash of the cert or CN
return request.META.get('SSL_CLIENT_S_DN_CN', 'unknown')
return 'no_cert'
@ratelimit(key='get_client_cert_id', rate='100/m', block=True)
def api_endpoint(request):
if request.limited:
return JsonResponse({'error': 'rate limit exceeded'}, status=429)
# Process request safely
return JsonResponse({'status': 'ok'})
3. Limit request size and payload parsing globally
Prevent large request bodies from consuming excessive memory by setting DATA_UPLOAD_MAX_MEMORY_SIZE and FILE_UPLOAD_MAX_MEMORY_SIZE. Combine this with size validation in serializers.
from django.conf import settings
# settings.py
DATA_UPLOAD_MAX_MEMORY_SIZE = 5_242_880 # 5 MB
FILE_UPLOAD_MAX_MEMORY_SIZE = 5_242_880
# In a view or serializer, enforce strict size/content-type checks:
from rest_framework import serializers
class SecureUploadSerializer(serializers.Serializer):
file = serializers.FileField(max_length=5_242_880)
def validate_file(self, value):
if value.size > 5_242_880:
raise serializersValidationError('File too large.')
return value
4. Use middleware to enforce concurrency and connection caps per certificate
Implement lightweight middleware that tracks active work per client identity and rejects or delays requests when thresholds are exceeded. This complements external load balancer limits.
import time
from django.utils.deprecation import MiddlewareMixin
class MTLSResourceGuardMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
super().__init__(get_response)
self.active = {}
self.max_per_client = 20 # tune per deployment
self.window = 60 # seconds
def process_request(self, request):
client_id = request.META.get('SSL_CLIENT_S_DN_CN')
if not client_id:
return
now = time.time()
# cleanup
self.active[client_id] = [t for t in self.active.get(client_id, []) if now - t < self.window]
if len(self.active[client_id]) >= self.max_per_client:
from django.http import HttpResponseServerError
return HttpResponseServerError('Too many concurrent requests')
self.active[client_id].append(now)
5. Integrate with infrastructure-level protections
While Django can enforce limits, it is best practice to also apply connection and rate controls at the load balancer or API gateway that handles mutual TLS. This ensures that resource exhaustion is mitigated before requests reach Django. Use middleBrick’s dashboard or CLI to continuously scan your mTLS-enabled endpoints and validate that rate limiting and input constraints are correctly reflected in your OpenAPI spec and runtime behavior.