1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
Description: Malformed URLs from user input incorrectly validated (CVE-2014-3730)
The validation for redirects did not correctly validate some malformed
URLs, which are accepted by some browsers. This allows a user to be
redirected to an unsafe URL unexpectedly.
.
Django relies on user input in some cases (e.g.
django.contrib.auth.views.login, django.contrib.comments, and i18n) to
redirect the user to an "on success" URL. The security checks for these
redirects (namely django.util.http.is_safe_url()) did not correctly
validate some malformed URLs, such as http:\\\djangoproject.com, which
are accepted by some browsers with more liberal URL parsing.
.
To remedy this, the validation in is_safe_url() has been tightened to
be able to handle and correctly validate these malformed URLs.
Origin: backport, https://github.com/django/django/commit/7feb54bbae3f637ab3c4dd4831d4385964f574df
Author: Salvatore Bonaccorso <carnil@debian.org>
Last-Update: 2014-05-18
---
django/contrib/auth/tests/views.py | 2 ++
django/utils/http.py | 12 ++++++++++++
2 files changed, 14 insertions(+)
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -132,7 +132,19 @@ def is_safe_url(url, host=None):
"""
if not url:
return False
+ # Chrome treats \ completely as /
+ url = url.replace('\\', '/')
+ # Chrome considers any URL with more than two slashes to be absolute, but
+ # urlaprse is not so flexible. Treat any url with three slashes as unsafe.
+ if url.startswith('///'):
+ return False
url_info = urlparse.urlparse(url)
+ # Forbid URLs like http:///example.com - with a scheme, but without a hostname.
+ # In that URL, example.com is not the hostname but, a path component. However,
+ # Chrome will still consider example.com to be the hostname, so we must not
+ # allow this syntax.
+ if not url_info[1] and url_info[0]:
+ return False
return (not url_info[1] or url_info[1] == host) and \
(not url_info[0] or url_info[0] in ['http', 'https'])
--- a/django/contrib/auth/tests/views.py
+++ b/django/contrib/auth/tests/views.py
@@ -229,8 +229,10 @@ class LoginTest(AuthViewsTestCase):
# Those URLs should not pass the security check
for bad_url in ('http://example.com',
+ 'http:///example.com',
'https://example.com',
'ftp://exampel.com',
+ '///example.com',
'//example.com',
'javascript:alert("XSS")'):
|