diff options
| author | Florian Apolloner <florian@apolloner.eu> | 2014-07-17 21:59:28 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2014-08-20 11:43:43 -0400 |
| commit | da051da8df5e69944745072611351d4cfc6435d5 (patch) | |
| tree | 4a491f8a733a636f91b62b1d45d13deed9da42b1 | |
| parent | 52b878d805c2dc810ddc1ea5493bb7b86455eacc (diff) | |
[1.6.x] Prevented reverse() from generating URLs pointing to other hosts.
This is a security fix. Disclosure following shortly.
| -rw-r--r-- | django/core/urlresolvers.py | 6 | ||||
| -rw-r--r-- | docs/releases/1.4.14.txt | 13 | ||||
| -rw-r--r-- | docs/releases/1.5.9.txt | 13 | ||||
| -rw-r--r-- | docs/releases/1.6.6.txt | 13 | ||||
| -rw-r--r-- | tests/urlpatterns_reverse/tests.py | 3 | ||||
| -rw-r--r-- | tests/urlpatterns_reverse/urls.py | 3 |
6 files changed, 50 insertions, 1 deletions
diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index b3008e88c4..4f251ab4ce 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -435,7 +435,11 @@ class RegexURLResolver(LocaleRegexProvider): candidate_pat = prefix_norm.replace('%', '%%') + result if re.search('^%s%s' % (prefix_norm, pattern), candidate_pat % candidate_subs, re.UNICODE): candidate_subs = dict((k, urlquote(v)) 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. diff --git a/docs/releases/1.4.14.txt b/docs/releases/1.4.14.txt index d0032e5399..28390c96a4 100644 --- a/docs/releases/1.4.14.txt +++ b/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. diff --git a/docs/releases/1.5.9.txt b/docs/releases/1.5.9.txt index 4a5233a1fd..12b5b5f806 100644 --- a/docs/releases/1.5.9.txt +++ b/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. diff --git a/docs/releases/1.6.6.txt b/docs/releases/1.6.6.txt index 0a4519b04d..43b3adf630 100644 --- a/docs/releases/1.6.6.txt +++ b/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 ======== diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py index 249acc1e37..7df4acf88a 100644 --- a/tests/urlpatterns_reverse/tests.py +++ b/tests/urlpatterns_reverse/tests.py @@ -147,6 +147,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'], {}), ) class NoURLPatternsTests(TestCase): diff --git a/tests/urlpatterns_reverse/urls.py b/tests/urlpatterns_reverse/urls.py index ac112c69cb..74c881eb1b 100644 --- a/tests/urlpatterns_reverse/urls.py +++ b/tests/urlpatterns_reverse/urls.py @@ -71,4 +71,7 @@ urlpatterns = patterns('', (r'defaults_view2/(?P<arg1>\d+)/', 'defaults_view', {'arg2': 2}, 'defaults'), url('^includes/', include(other_patterns)), + + # Security tests + url('(.+)/security/$', empty_view, name='security'), ) |
