Missing Tls in Django with Mutual Tls
Missing Tls in Django with Mutual Tls — how this specific combination creates or exposes the vulnerability
Mutual Transport Layer Security (mTLS) requires both the client and the server to present and validate certificates. In Django, relying solely on standard HTTPS settings without enforcing client certificates can create a gap when mTLS is expected but not correctly implemented. A common misconfiguration is setting SECURE_SSL_REDIRECT = True and terminating TLS at a load balancer or proxy while neglecting to validate the client certificate on the application side. When TLS is present but mutual authentication is missing or bypassed, the channel is encrypted, yet the identity of the connecting client is not verified. This can expose internal endpoints to unauthenticated or mis-authenticated clients that should have been rejected.
With middleBrick’s 12 checks running in parallel, the scanner tests unauthenticated attack surfaces and flags issues such as missing client certificate validation under Authentication and BOLA/IDOR, and insecure transport configurations under Encryption. For example, an endpoint expecting mTLS but missing SSL_CLIENT_VERIFY checks in Django can allow an attacker who controls a network position to interact with the API as if they were a valid client. This becomes critical when sensitive operations rely on the assumption that only authorized clients possessing a trusted certificate can proceed.
Django’s built-in support for mTLS is minimal and usually relies on the underlying web server (e.g., Nginx, HAProxy) or a reverse proxy to handle certificate verification, then passing the result to Django via headers like HTTP_X_SSL_CLIENT_VERIFY or SSL_CLIENT_VERIFY. If these headers are trusted without strict validation, spoofing becomes possible. The scanner’s Input Validation and Property Authorization checks help detect whether the application safely uses these headers and whether authorization logic accounts for the verified certificate identity.
Real-world attack patterns include scenarios where TLS is enabled but client certificates are optional or ignored. An unauthenticated LLM endpoint might be inadvertently exposed if the service is also used for AI-related tooling, and mTLS is not consistently enforced. middleBrick’s LLM/AI Security checks specifically look for unauthenticated LLM endpoints and system prompt leakage, which can compound risks when mTLS expectations are not met.
Compliance frameworks such as OWASP API Top 10 (2023) A07:2023 — Identification and Authentication Failures, and PCI-DSS requirements for strong cryptography and mutual authentication highlight the need to properly implement mTLS. A misalignment between TLS termination and Django-level validation can lead to findings in Encryption and Authentication categories, with remediation guidance focused on strict client certificate validation and secure header usage.
Mutual Tls-Specific Remediation in Django — concrete code fixes
To correctly implement mTLS in Django, you must ensure that the web server or reverse proxy terminates TLS and validates client certificates, then securely forwards verification results to Django. Django should never directly handle certificate validation but must rigorously validate the headers set by the proxy and enforce authorization based on certificate identity.
Example Nginx configuration for mTLS:
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
ssl_client_certificate /etc/ssl/certs/ca.crt;
ssl_verify_client on;
location /api/ {
proxy_pass http://django_app;
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
proxy_set_header X-SSL-Client-Cert $ssl_client_cert;
}
}
In Django settings, configure secure header handling and strict validation:
import os
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# Only if behind a trusted proxy that sets these headers
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Custom middleware to validate client certificate presence and status
class MutualTlsValidationMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
verify_status = request.META.get('HTTP_X_SSL_CLIENT_VERIFY', '')
if verify_status != 'SUCCESS':
# Reject requests without a valid client certificate
from django.http import HttpResponseForbidden
return HttpResponseForbidden('Client certificate required.')
# Optionally inspect the DN for additional authorization
client_dn = request.META.get('HTTP_X_SSL_CLIENT_DN', '')
request.client_dn = client_dn
response = self.get_response(request)
return response
Ensure the middleware is placed after security-related middleware but before view resolution. Use the verified DN or a mapped certificate field to enforce fine-grained permissions:
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
@login_required
def sensitive_view(request):
# Example: map certificate DN to a user role or policy
if not request.user.has_perm('api.access_sensitive'):
from django.http import HttpResponseForbidden
return HttpResponseForbidden('Insufficient privileges.')
# Proceed with logic
return HttpResponse('Authorized access.')
For production, combine this with rate limiting and continuous monitoring. middleBrick’s Pro plan offers continuous monitoring and CI/CD integration so that any regression in mTLS enforcement can be caught before deployment. The GitHub Action can fail builds if security score thresholds are not met, ensuring that missing client certificate validation does not reach production.
When using the CLI to verify your configuration, run:
middlebrick scan https://api.example.com
The scanner will report findings in Authentication and Encryption, helping you confirm that mTLS is correctly enforced and that no unauthenticated pathways remain.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |