1
0
mirror of https://github.com/django/django.git synced 2025-07-05 02:09:13 +00:00

[1.2.X] Prevented non-admin users from accessing the admin redirect shortcut.

If the admin shortcut view (e.g. /admin/r/<content-type>/<pk>/) is
publically-accessible, and if a public users can guess a content-type ID
(which isn't hard given that they're sequential), then the redirect view could
possibly leak data by redirecting to pages a user shouldn't "know about." So
the redirect view needs the same protection as the rest of the admin site.

Thanks to Jason Royes for pointing this out.

Backport of [15639] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15640 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss 2011-02-24 13:38:32 +00:00
parent fa1a74ff3c
commit 062cbfb1ec
2 changed files with 23 additions and 2 deletions

View File

@ -3,6 +3,7 @@ from django import http, template
from django.contrib.admin import ModelAdmin from django.contrib.admin import ModelAdmin
from django.contrib.admin import actions from django.contrib.admin import actions
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.contrib.contenttypes import views as contenttype_views
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
@ -225,7 +226,7 @@ class AdminSite(object):
wrap(self.i18n_javascript, cacheable=True), wrap(self.i18n_javascript, cacheable=True),
name='jsi18n'), name='jsi18n'),
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$',
'django.views.defaults.shortcut'), wrap(contenttype_views.shortcut)),
url(r'^(?P<app_label>\w+)/$', url(r'^(?P<app_label>\w+)/$',
wrap(self.app_index), wrap(self.app_index),
name='app_list') name='app_list')

View File

@ -1026,7 +1026,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
self.assertContains(response, should_contain) self.assertContains(response, should_contain)
class SecureViewTest(TestCase): class SecureViewTests(TestCase):
fixtures = ['admin-views-users.xml'] fixtures = ['admin-views-users.xml']
def setUp(self): def setUp(self):
@ -1150,6 +1150,25 @@ class SecureViewTest(TestCase):
# make sure the view removes test cookie # make sure the view removes test cookie
self.assertEqual(self.client.session.test_cookie_worked(), False) self.assertEqual(self.client.session.test_cookie_worked(), False)
def test_shortcut_view_only_available_to_staff(self):
"""
Only admin users should be able to use the admin shortcut view.
"""
user_ctype = ContentType.objects.get_for_model(User)
user = User.objects.get(username='super')
shortcut_url = "/test_admin/admin/r/%s/%s/" % (user_ctype.pk, user.pk)
# Not logged in: we should see the login page.
response = self.client.get(shortcut_url, follow=False)
self.assertTemplateUsed(response, 'admin/login.html')
# Logged in? Redirect.
self.client.login(username='super', password='secret')
response = self.client.get(shortcut_url, follow=False)
# Can't use self.assertRedirects() because User.get_absolute_url() is silly.
self.assertEqual(response.status_code, 302)
self.assertEqual(response['Location'], 'http://example.com/users/super/')
class AdminViewUnicodeTest(TestCase): class AdminViewUnicodeTest(TestCase):
fixtures = ['admin-views-unicode.xml'] fixtures = ['admin-views-unicode.xml']
@ -2670,3 +2689,4 @@ class DateHierarchyTests(TestCase):
self.assert_non_localized_year(response, 2000) self.assert_non_localized_year(response, 2000)
self.assert_non_localized_year(response, 2003) self.assert_non_localized_year(response, 2003)
self.assert_non_localized_year(response, 2005) self.assert_non_localized_year(response, 2005)