A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/django/django/commit/2a446c896e7c814661fb9c4f212b071b2a7fa446 below:

[1.5.x] Prevented data leakage in contrib.admin via query string mani… · django/django@2a446c8 · GitHub

File tree Expand file treeCollapse file tree 6 files changed

+76

-5

lines changed

Filter options

Expand file treeCollapse file tree 6 files changed

+76

-5

lines changed Original file line number Diff line number Diff line change

@@ -0,0 +1,6 @@

1 +

from django.core.exceptions import SuspiciousOperation

2 + 3 + 4 +

class DisallowedModelAdminToField(SuspiciousOperation):

5 +

"""Invalid to_field was passed to admin view via URL query string"""

6 +

pass

Original file line number Diff line number Diff line change

@@ -275,6 +275,24 @@ def lookup_allowed(self, lookup, value):

275 275

clean_lookup = LOOKUP_SEP.join(parts)

276 276

return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy

277 277 278 +

def to_field_allowed(self, request, to_field):

279 +

opts = self.model._meta

280 + 281 +

try:

282 +

field = opts.get_field(to_field)

283 +

except FieldDoesNotExist:

284 +

return False

285 + 286 +

# Make sure at least one of the models registered for this site

287 +

# references this field.

288 +

registered_models = self.admin_site._registry

289 +

for related_object in opts.get_all_related_objects():

290 +

if (related_object.model in registered_models and

291 +

field == related_object.field.rel.get_related_field()):

292 +

return True

293 + 294 +

return False

295 + 278 296

def has_add_permission(self, request):

279 297

"""

280 298

Returns True if the given request has permission to add an object.

Original file line number Diff line number Diff line change

@@ -12,6 +12,7 @@

12 12

from django.utils.http import urlencode

13 13 14 14

from django.contrib.admin import FieldListFilter

15 +

from django.contrib.admin.exceptions import DisallowedModelAdminToField

15 16

from django.contrib.admin.options import IncorrectLookupParameters

16 17

from django.contrib.admin.util import (quote, get_fields_from_path,

17 18

lookup_needs_distinct, prepare_lookup_value)

@@ -58,7 +59,10 @@ def __init__(self, request, model, list_display, list_display_links,

58 59

self.page_num = 0

59 60

self.show_all = ALL_VAR in request.GET

60 61

self.is_popup = IS_POPUP_VAR in request.GET

61 -

self.to_field = request.GET.get(TO_FIELD_VAR)

62 +

to_field = request.GET.get(TO_FIELD_VAR)

63 +

if to_field and not model_admin.to_field_allowed(request, to_field):

64 +

raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

65 +

self.to_field = to_field

62 66

self.params = dict(request.GET.items())

63 67

if PAGE_VAR in self.params:

64 68

del self.params[PAGE_VAR]

Original file line number Diff line number Diff line change

@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between

47 47

requests without an intervening logout could result in the prior user's session

48 48

being co-opted by the subsequent user. The middleware now logs the user out on

49 49

a failed login attempt.

50 + 51 +

Data leakage via query string manipulation in ``contrib.admin``

52 +

===============================================================

53 + 54 +

In older versions of Django it was possible to reveal any field's data by

55 +

modifying the "popup" and "to_field" parameters of the query string on an admin

56 +

change form page. For example, requesting a URL like

57 +

``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed

58 +

viewing the password hash of each user. While the admin requires users to have

59 +

permissions to view the change form pages in the first place, this could leak

60 +

data if you rely on users having access to view only certain fields on a model.

61 + 62 +

To address the issue, an exception will now be raised if a ``to_field`` value

63 +

that isn't a related field to a model that has been registered with the admin

64 +

is specified.

Original file line number Diff line number Diff line change

@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between

47 47

requests without an intervening logout could result in the prior user's session

48 48

being co-opted by the subsequent user. The middleware now logs the user out on

49 49

a failed login attempt.

50 + 51 +

Data leakage via query string manipulation in ``contrib.admin``

52 +

===============================================================

53 + 54 +

In older versions of Django it was possible to reveal any field's data by

55 +

modifying the "popup" and "to_field" parameters of the query string on an admin

56 +

change form page. For example, requesting a URL like

57 +

``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed

58 +

viewing the password hash of each user. While the admin requires users to have

59 +

permissions to view the change form pages in the first place, this could leak

60 +

data if you rely on users having access to view only certain fields on a model.

61 + 62 +

To address the issue, an exception will now be raised if a ``to_field`` value

63 +

that isn't a related field to a model that has been registered with the admin

64 +

is specified.

Original file line number Diff line number Diff line change

@@ -16,11 +16,12 @@

16 16

from django.core.urlresolvers import reverse

17 17

# Register auth models with the admin.

18 18

from django.contrib import admin

19 +

from django.contrib.admin.exceptions import DisallowedModelAdminToField

19 20

from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME

20 21

from django.contrib.admin.models import LogEntry, DELETION

21 22

from django.contrib.admin.sites import LOGIN_FORM_KEY

22 23

from django.contrib.admin.util import quote

23 -

from django.contrib.admin.views.main import IS_POPUP_VAR

24 +

from django.contrib.admin.views.main import IS_POPUP_VAR, TO_FIELD_VAR

24 25

from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase

25 26

from django.contrib.auth import REDIRECT_FIELD_NAME

26 27

from django.contrib.auth.models import Group, User, Permission, UNUSABLE_PASSWORD

@@ -557,6 +558,19 @@ def test_disallowed_filtering(self):

557 558

response = self.client.get("/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=%d" % e1.pk)

558 559

self.assertEqual(response.status_code, 200)

559 560 561 +

def test_disallowed_to_field(self):

562 +

with self.assertRaises(DisallowedModelAdminToField):

563 +

response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'missing_field'})

564 + 565 +

# Specifying a field that is not refered by any other model registered

566 +

# to this admin site should raise an exception.

567 +

with self.assertRaises(DisallowedModelAdminToField):

568 +

response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'name'})

569 + 570 +

# Specifying a field referenced by another model should be allowed.

571 +

response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'})

572 +

self.assertEqual(response.status_code, 200)

573 + 560 574

def test_allowed_filtering_15103(self):

561 575

"""

562 576

Regressions test for ticket 15103 - filtering on fields defined in a

@@ -2138,10 +2152,9 @@ def test_with_fk_to_field(self):

2138 2152

"""Ensure that the to_field GET parameter is preserved when a search

2139 2153

is performed. Refs #10918.

2140 2154

"""

2141 -

from django.contrib.admin.views.main import TO_FIELD_VAR

2142 -

response = self.client.get('/test_admin/admin/auth/user/?q=joe&%s=username' % TO_FIELD_VAR)

2155 +

response = self.client.get('/test_admin/admin/auth/user/?q=joe&%s=id' % TO_FIELD_VAR)

2143 2156

self.assertContains(response, "\n1 user\n")

2144 -

self.assertContains(response, '<input type="hidden" name="t" value="username"/>', html=True)

2157 +

self.assertContains(response, '<input type="hidden" name="%s" value="id"/>' % TO_FIELD_VAR, html=True)

2145 2158 2146 2159

def test_exact_matches(self):

2147 2160

response = self.client.get('/test_admin/admin/admin_views/recommendation/?q=bar')

You can’t perform that action at this time.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4