#23815 closed Bug (fixed)
CsrfViewMiddleware UnicodeDecodeError
Reported by: | codeitloadit | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | dev |
Severity: | Normal | Keywords: | middleware CsrfViewMiddleware UnicodeDecodeError |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The csrf middleware is raising an exception when the HTTP_REFERER contains non-ascii characters. Since this code is attempting to validate the referer, I would expect these request to just be rejected and return 403.
Here is the code in django/middleware/csrf.py
:
referer = request.META.get('HTTP_REFERER') if referer is None: return self._reject(request, REASON_NO_REFERER) # Note that request.get_host() includes the port. good_referer = 'https://%s/' % request.get_host() if not same_origin(referer, good_referer): reason = REASON_BAD_REFERER % (referer, good_referer) return self._reject(request, reason)
This issue is very similar to https://code.djangoproject.com/ticket/20356 which was patched by https://github.com/django/django/commit/8fd44b2551b9cca765b216a31306f9c6935f1492 which just encodes the referer like so:
referer = force_text(request.META.get('HTTP_REFERER', ''), errors='replace')
Change History (10)
comment:1 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Uncategorized → Bug |
Version: | 1.6 → master |
comment:2 by , 10 years ago
Resolution: | → needsinfo |
---|---|
Status: | new → closed |
comment:3 by , 10 years ago
Resolution: | needsinfo |
---|---|
Status: | closed → new |
I've seen this in production: Django 1.6.5, Python 2.7, and here are some examples of REFERER
causing the issue:
'\xd8B\xf6I\xdf'
'|\xcaH'
Let me know if I can be of any help resolving this issue.
comment:4 by , 10 years ago
Can you test with Django 1.7 and/or master? 1.6 is only receiving security fixes so if this issue has been fixed since then we can close the ticket.
comment:5 by , 10 years ago
I was able to reproduce with Django 1.7.2/Python 2.7.9. Reproducing requires accessing Django using HTTPS, because the affected code is behind if request.is_secure():
. To achieve this, I used the django-sslserver
application (https://github.com/teddziuba/django-sslserver) in conjunction with a simple project with the Django admin enabled. Using the requests
module to supply a bad REFERER
header when POST-ing to the admin login page:
import requests requests.post('https://localhost:8000/admin/login/', headers={'referer': '\xd8B\xf6I\xdf'}, verify=False).text
I get the UnicodeDecodeError
.
comment:6 by , 10 years ago
Reproducible with:
-
tests/csrf_tests/tests.py
diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py index 9c6e2e5..f22cddb 100644
a b class CsrfViewMiddlewareTest(TestCase): 300 300 req2 = CsrfViewMiddleware().process_view(req, post_form_view, (), {}) 301 301 self.assertNotEqual(None, req2) 302 302 self.assertEqual(403, req2.status_code) 303 # Non-ASCII 304 req.META['HTTP_REFERER'] = b'\xd8B\xf6I\xdf' 305 req2 = CsrfViewMiddleware().process_view(req, post_form_view, (), {}) 306 self.assertNotEqual(None, req2) 307 self.assertEqual(403, req2.status_code) 303 308 304 309 @override_settings(ALLOWED_HOSTS=['www.example.com']) 305 310 def test_https_good_referer(self):
comment:8 by , 10 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:9 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Cannot repeat that error, I've tested it with several different unicode chars in REFERER and it works correctly.