فهرست منبع

Prevented reverse() from generating URLs pointing to other hosts.

This is a security fix. Disclosure following shortly.
Florian Apolloner 10 سال پیش
والد
کامیت
28e765810d

+ 5 - 1
django/core/urlresolvers.py

@@ -456,7 +456,11 @@ class RegexURLResolver(LocaleRegexProvider):
                     # safe characters from `pchar` definition of RFC 3986
                     candidate_subs = dict((k, urlquote(v, safe=RFC3986_SUBDELIMS + str('/~:@')))
                                           for (k, v) in candidate_subs.items())
-                    return candidate_pat % candidate_subs
+                    url = candidate_pat % candidate_subs
+                    # Don't allow construction of scheme relative urls.
+                    if url.startswith('//'):
+                        url = '/%%2F%s' % url[2:]
+                    return url
         # lookup_view can be URL label, or dotted path, or callable, Any of
         # these can be passed in at the top, but callables are not friendly in
         # error messages.

+ 13 - 0
docs/releases/1.4.14.txt

@@ -5,3 +5,16 @@ Django 1.4.14 release notes
 *Under development*
 
 Django 1.4.14 fixes several security issues in 1.4.13.
+
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs  (URLs
+starting with two slashes), which could unexpectedly redirect a user  to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.

+ 13 - 0
docs/releases/1.5.9.txt

@@ -5,3 +5,16 @@ Django 1.5.9 release notes
 *Under development*
 
 Django 1.5.9 fixes several security issues in 1.5.8.
+
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs  (URLs
+starting with two slashes), which could unexpectedly redirect a user  to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.

+ 13 - 0
docs/releases/1.6.6.txt

@@ -6,6 +6,19 @@ Django 1.6.6 release notes
 
 Django 1.6.6 fixes several security issues and bugs in 1.6.5.
 
+:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
+=======================================================================================
+
+In certain situations, URL reversing could generate scheme-relative URLs  (URLs
+starting with two slashes), which could unexpectedly redirect a user  to a
+different host. An attacker could exploit this, for example, by redirecting
+users to a phishing site designed to ask for user's passwords.
+
+To remedy this, URL reversing now ensures that no URL starts with two slashes
+(//), replacing the second slash with its URL encoded counterpart (%2F). This
+approach ensures that semantics stay the same, while making the URL relative to
+the domain and not to the scheme.
+
 Bugfixes
 ========
 

+ 3 - 0
tests/urlpatterns_reverse/tests.py

@@ -152,6 +152,9 @@ test_data = (
     ('defaults', '/defaults_view2/3/', [], {'arg1': 3, 'arg2': 2}),
     ('defaults', NoReverseMatch, [], {'arg1': 3, 'arg2': 3}),
     ('defaults', NoReverseMatch, [], {'arg2': 1}),
+
+    # Security tests
+    ('security', '/%2Fexample.com/security/', ['/example.com'], {}),
 )
 
 

+ 3 - 0
tests/urlpatterns_reverse/urls.py

@@ -75,4 +75,7 @@ with warnings.catch_warnings(record=True):
         (r'defaults_view2/(?P<arg1>[0-9]+)/', defaults_view, {'arg2': 2}, 'defaults'),
 
         url('^includes/', include(other_patterns)),
+
+        # Security tests
+        url('(.+)/security/$', empty_view, name='security'),
     )