Listen to this Post
How the CVE Works
This vulnerability in Django (versions 5.2 before 5.2.2, 5.1 before 5.1.10, and 4.2 before 4.2.22) stems from insufficient escaping of `request.path` in HTTP response logging. Attackers can craft malicious URLs containing escape sequences or control characters, which are then logged without proper sanitization. When these logs are viewed in terminals or processed by log analysis tools, the injected sequences can manipulate output—enabling log forgery, terminal escape code execution, or log poisoning. This could obscure attacks or trigger unintended behavior in log parsers.
DailyCVE Form
Platform: Django
Version: <5.2.2, <5.1.10, <4.2.22
Vulnerability: Log injection
Severity: Moderate
Date: 2025-06-05
Prediction: Patch expected by 2025-06-12
What Undercode Say:
Exploitation
1. Craft malicious URL:
GET /path%0A%1B[31m[bash]%20Admin%20login%20attempt%1B[0m HTTP/1.1
2. Trigger logging:
curl http://vulnerable-django-app.com/$(python3 -c "print('%1B[41mINJECTED%1B[0m')")
3. View poisoned logs: Terminal displays colored/spoofed entries.
Protection
1. Update Django:
pip install --upgrade django==5.2.2
2. Sanitize logs manually (temporary fix):
settings.py LOGGING = { 'filters': { 'escape_path': { '()': 'django.utils.log.EscapePathFilter', }, }, }
3. Validate logs externally:
awk '/\x1B[[0-9;][bash]/ {print "Suspected ANSI injection:", $0}' /var/log/django.log
Detection
1. Scan logs for anomalies:
grep -P "[\x00-\x1F\x7F]" /var/log/django/.log
2. Monitor for abnormal requests:
middleware.py class LogInspectionMiddleware: def process_request(self, request): if any(ord(c) < 32 for c in request.path): raise SuspiciousOperation("Control character in path")
Analytics
- Affected systems: Django apps with debug/access logging enabled.
- Risk vector: Log viewers/analyzers parsing raw terminal sequences.
- Mitigation urgency: Medium (requires log reprocessing if exploited).
Patch Analysis
The fix escapes `request.path` using `repr()` before logging:
patched django/core/handlers/base.py log_response( "%s: %s", repr(request.path), response.reason_phrase )
References
Sources:
Reported By: github.com
Extra Source Hub:
Undercode