HIGH header injectiondjango

Header Injection in Django

How Header Injection Manifests in Django

Header injection in Django occurs when user-controlled data flows into HTTP response headers without proper validation. Django's architecture creates several unique attack vectors for this vulnerability.

The most common pattern involves Django's JsonResponse and StreamingHttpResponse objects. When developers dynamically set headers using user input, they often overlook the security implications. For example:

def vulnerable_view(request):
user_agent = request.headers.get('User-Agent')
response = JsonResponse({'status': 'ok'})
response['X-Client-Type'] = user_agent # Vulnerable
return response

This allows an attacker to inject CRLF sequences (%0D%0A) into the User-Agent header, potentially adding arbitrary response headers or even splitting responses.

Django's middleware system creates another attack surface. Custom middleware that processes request headers and sets response headers without sanitization can be exploited. Consider this middleware:

class HeaderProcessingMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
response = self.get_response(request)
if referer:
response['X-Referer-Source'] = referer # Vulnerable
return response

Template rendering with custom headers presents a third vector. Developers sometimes use response.set_cookie() or response['Set-Cookie'] with user-controlled values:

def profile_view(request):
username = request.GET.get('username', 'default')
response = render(request, 'profile.html')
response.set_cookie('username', username) # Vulnerable if username contains CRLF
return response

Django's StreamingHttpResponse is particularly dangerous because it allows incremental header modification. An attacker could exploit timing issues to inject headers mid-response in long-running streams.

The Django REST Framework (DRF) adds additional complexity. DRF's Response class and renderer system can inadvertently expose header injection vulnerabilities when custom renderers process user input for header values.

Django-Specific Detection

Detecting header injection in Django applications requires both manual code review and automated scanning. middleBrick's black-box scanning approach is particularly effective for Django applications because it tests the actual running API without requiring source code access.

middleBrick scans for header injection by sending requests with crafted header values containing CRLF sequences and observing the response. For Django applications, it specifically tests:

  • Common Django response patterns including JsonResponse, StreamingHttpResponse, and HttpResponse
  • Middleware header processing logic by sending headers through the full request pipeline
  • DRF renderers and response objects
  • Cookie handling in Django's session and authentication middleware

The scanner sends payloads like:

GET /api/data HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 X-Injected-Header: injected-value

If the response contains the injected header or shows signs of header splitting, middleBrick flags this as a vulnerability with severity assessment based on the potential impact.

For development teams, middleBrick's GitHub Action integration allows continuous scanning of Django APIs in CI/CD pipelines. You can configure it to fail builds when header injection vulnerabilities are detected:

jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run middleBrick scan
run: middlebrick scan https://staging.example.com/api/ --fail-on-severity=medium

middleBrick's OpenAPI analysis also helps identify potential header injection points by cross-referencing your Django REST Framework's API schema with runtime behavior, highlighting endpoints where user input might flow into headers.

Django-Specific Remediation

Remediating header injection in Django requires a defense-in-depth approach using Django's built-in security features and proper input validation.

The first line of defense is Django's django.utils.http.strip_unsafe_headers() utility, which removes potentially dangerous headers. Use it when processing user input for headers:

from django.utils.http import strip_unsafe_headers

def safe_header_view(request):
user_agent = request.headers.get('User-Agent', '')
clean_agent = strip_unsafe_headers(user_agent)
response = JsonResponse({'status': 'ok'})
response['X-Client-Type'] = clean_agent
return response

For more comprehensive protection, create a custom middleware that sanitizes all headers before they're set in responses:

import re
from django.utils.http import headers

class HeaderSanitizationMiddleware:
CRLF_PATTERN = re.compile(r'[ ]+')

def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
response = self.get_response(request)
for header in list(response.items()):
if self.CRLF_PATTERN.search(header[1]):
del response[header[0]]
return response

Django's SafeString and template auto-escaping features help prevent header injection in template contexts. When setting headers from template variables, use Django's safe string utilities:

from django.utils.safestring import SafeString

def template_header_view(request):
username = request.GET.get('username', 'guest')
safe_username = SafeString(username.replace(' ', '').replace(' ', ''))
response = render(request, 'template.html', {'username': safe_username})
response['X-Username'] = username
return response

For Django REST Framework applications, use DRF's serializer validation to sanitize header values before they're used:

from rest_framework import serializers

class HeaderSerializer(serializers.Serializer):
custom_header = serializers.CharField(max_length=100, required=False)

def validate_custom_header(self, value):
if ' ' in value or ' ' in value:
raise serializers.ValidationError('Header injection detected')
return value

middleBrick's continuous monitoring plan can help verify that these remediations remain effective over time, automatically scanning your Django APIs on a configurable schedule and alerting your team if new header injection vulnerabilities are detected.

Frequently Asked Questions

How does middleBrick detect header injection in Django applications?
middleBrick uses black-box scanning to test Django applications without requiring source code access. It sends requests with crafted header values containing CRLF sequences and analyzes responses for signs of header injection. The scanner specifically tests Django's JsonResponse, StreamingHttpResponse, middleware processing, and DRF renderers. When header injection is detected, middleBrick provides a detailed report with severity assessment and remediation guidance mapped to OWASP API Top 10 standards.
Can I integrate middleBrick scanning into my Django CI/CD pipeline?
Yes, middleBrick offers a GitHub Action that integrates seamlessly with Django projects. You can add it to your workflow to automatically scan Django APIs in staging environments before deployment. The action can be configured to fail builds if security scores drop below your threshold or if header injection vulnerabilities are detected. This ensures that security issues are caught early in development rather than in production.