Ticket #11457: 11457.patch

File 11457.patch, 2.9 KB (added by Bruno Renié, 14 years ago)

The suggested fix in the ticket summary is not enough, see my comment next.

  • django/contrib/auth/views.py

     
    2626        form = authentication_form(data=request.POST)
    2727        if form.is_valid():
    2828            # Light security check -- make sure redirect_to isn't garbage.
    29             if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
     29            if not redirect_to or redirect_to.startswith('//') \
     30                    or redirect_to.startswith('http://') or ' ' in redirect_to:
    3031                redirect_to = settings.LOGIN_REDIRECT_URL
    3132            from django.contrib.auth import login
    3233            login(request, form.get_user())
  • django/contrib/auth/tests/views.py

     
    22import re
    33
    44from django.conf import settings
    5 from django.contrib.auth import SESSION_KEY
     5from django.contrib.auth import SESSION_KEY, REDIRECT_FIELD_NAME
    66from django.contrib.auth.forms import AuthenticationForm
    77from django.contrib.sites.models import Site, RequestSite
    88from django.contrib.auth.models import User
     
    183183        self.assertEquals(response.context['site_name'], site.name)
    184184        self.assert_(isinstance(response.context['form'], AuthenticationForm),
    185185                     'Login form is not an AuthenticationForm')
     186
     187    def test_security_check(self, password='password'):
     188        import urllib
     189        login_url = reverse('django.contrib.auth.views.login')
     190
     191        # This URL should not pass the security check
     192        nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
     193            'url': login_url,
     194            'next': REDIRECT_FIELD_NAME,
     195            'bad_url': urllib.quote('http://example.com')
     196        }
     197        response = self.client.post(nasty_url, {
     198            'username': 'testclient',
     199            'password': password,
     200            }
     201        )
     202        self.assertEquals(response.status_code, 302)
     203        self.assertFalse('http://example.com' in response['Location'])
     204
     205        # Now, this URL has an other URL as a GET parameter and therefore
     206        # should be allowed
     207        url = '%(url)s?%(next)s=/view/?param=%(safe_param)s' % {
     208            'url': login_url,
     209            'next': REDIRECT_FIELD_NAME,
     210            'safe_param': urllib.quote('http://example.com')
     211        }
     212        response = self.client.post(url, {
     213            'username': 'testclient',
     214            'password': password,
     215            }
     216        )
     217        self.assertEquals(response.status_code, 302)
     218        self.assertTrue('/view/?param=http://example.com' in response['Location'])
     219
    186220       
    187221class LogoutTest(AuthViewsTestCase):
    188222    urls = 'django.contrib.auth.tests.urls'
Back to Top