diff options
| author | Simon Charette <charette.s@gmail.com> | 2014-08-11 15:36:16 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2014-08-11 16:01:41 -0400 |
| commit | 027bd348642007617518379f8b02546abacaa6e0 (patch) | |
| tree | 573f0e4f79c862f6f4983a0d0caab5b54facdf5a /django/contrib/admin | |
| parent | c9e3b9949cd55f090591fbdc4a114fcb8368b6d9 (diff) | |
[1.4.x] Prevented data leakage in contrib.admin via query string manipulation.
This is a security fix. Disclosure following shortly.
Diffstat (limited to 'django/contrib/admin')
| -rw-r--r-- | django/contrib/admin/exceptions.py | 6 | ||||
| -rw-r--r-- | django/contrib/admin/options.py | 18 | ||||
| -rw-r--r-- | django/contrib/admin/views/main.py | 6 |
3 files changed, 29 insertions, 1 deletions
diff --git a/django/contrib/admin/exceptions.py b/django/contrib/admin/exceptions.py new file mode 100644 index 0000000000..d9de47eefd --- /dev/null +++ b/django/contrib/admin/exceptions.py @@ -0,0 +1,6 @@ +from django.core.exceptions import SuspiciousOperation + + +class DisallowedModelAdminToField(SuspiciousOperation): + """Invalid to_field was passed to admin view via URL query string""" + pass diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 78a08cd120..cf3497b93c 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -269,6 +269,24 @@ class BaseModelAdmin(object): clean_lookup = LOOKUP_SEP.join(parts) return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy + def to_field_allowed(self, request, to_field): + opts = self.model._meta + + try: + field = opts.get_field(to_field) + except FieldDoesNotExist: + return False + + # Make sure at least one of the models registered for this site + # references this field. + registered_models = self.admin_site._registry + for related_object in opts.get_all_related_objects(): + if (related_object.model in registered_models and + field == related_object.field.rel.get_related_field()): + return True + + return False + def has_add_permission(self, request): """ Returns True if the given request has permission to add an object. diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index 9d5c30434d..7f4bb2f7e5 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -10,6 +10,7 @@ from django.utils.translation import ugettext, ugettext_lazy from django.utils.http import urlencode from django.contrib.admin import FieldListFilter +from django.contrib.admin.exceptions import DisallowedModelAdminToField from django.contrib.admin.options import IncorrectLookupParameters from django.contrib.admin.util import (quote, get_fields_from_path, lookup_needs_distinct, prepare_lookup_value) @@ -56,7 +57,10 @@ class ChangeList(object): self.page_num = 0 self.show_all = ALL_VAR in request.GET self.is_popup = IS_POPUP_VAR in request.GET - self.to_field = request.GET.get(TO_FIELD_VAR) + to_field = request.GET.get(TO_FIELD_VAR) + if to_field and not model_admin.to_field_allowed(request, to_field): + raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field) + self.to_field = to_field self.params = dict(request.GET.items()) if PAGE_VAR in self.params: del self.params[PAGE_VAR] |
