CVE-2016-2512 (Python, published 2016-04-08T15:59Z)
Description: value: The utils.http.is_safe_url function in Django before 1.8.10 and 1.9.x before 1.9.3 allows remote attackers to redirect users to arbitrary web sites and conduct phishing attacks or possibly conduct cross-site scripting (XSS) attacks via a URL containing basic authentication, as demonstrated by http://mysite.example.com\@attacker.com.
Severity: MEDIUM (CVSS v3 base score: 7.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/django/django
Files changed:
django/utils/http.py
docs/releases/1.8.10.txt
docs/releases/1.9.3.txt
tests/utils_tests/test_http.py
Commit message: Fixed CVE-2016-2512 -- Prevented spoofing is_safe_url() with basic auth.

This is a security fix.


Vulnerable code:
    # Chrome treats \ completely as /
    url = url.replace('\\', '/')

Fixed code:
    # Chrome treats \ completely as / in paths but it could be part of some
    # basic auth credentials so we need to check both URLs.
    return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)


def _is_safe_url(url, host):
CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth
===============================================================================================================

Django relies on user input in some cases (e.g.
:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
to redirect the user to an "on success" URL. The security check for these
redirects (namely ``django.utils.http.is_safe_url()``) considered some URLs
with basic authentication credentials "safe" when they shouldn't be.

For example, a URL like ``http://mysite.example.com\@attacker.com`` would be
considered safe if the request's host is ``http://mysite.example.com``, but
redirecting to this URL sends the user to ``attacker.com``.

Also, if a developer relies on ``is_safe_url()`` to provide safe redirect
targets and puts such a URL into a link, they could suffer from an XSS attack.

CVE-2016-2512: Malicious redirect and possible XSS attack via user-supplied redirect URLs containing basic auth
===============================================================================================================

Django relies on user input in some cases (e.g.
:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
to redirect the user to an "on success" URL. The security check for these
redirects (namely ``django.utils.http.is_safe_url()``) considered some URLs
with basic authentication credentials "safe" when they shouldn't be.

For example, a URL like ``http://mysite.example.com\@attacker.com`` would be
considered safe if the request's host is ``http://mysite.example.com``, but
redirecting to this URL sends the user to ``attacker.com``.

Also, if a developer relies on ``is_safe_url()`` to provide safe redirect
targets and puts such a URL into a link, they could suffer from an XSS attack.

                        r'http://otherserver\@example.com',
                        r'http:\\testserver\@example.com',
                        r'http://testserver\me:pass@example.com',
                        r'http://testserver\@example.com',
                        r'http:\\testserver\confirm\me@example.com',
                     'http://testserver/confirm?email=me@example.com',
        # Valid basic auth credentials are allowed.
        self.assertTrue(http.is_safe_url(r'http://user:pass@testserver/', host='user:pass@testserver'))
        # A path without host is allowed.
        self.assertTrue(http.is_safe_url('/confirm/me@example.com'))
        # Basic auth without host is not allowed.
        self.assertFalse(http.is_safe_url(r'http://testserver\@example.com'))