summaryrefslogtreecommitdiff
path: root/django/contrib/admin
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2014-08-11 15:36:16 -0400
committerTim Graham <timograham@gmail.com>2014-08-11 16:01:41 -0400
commit027bd348642007617518379f8b02546abacaa6e0 (patch)
tree573f0e4f79c862f6f4983a0d0caab5b54facdf5a /django/contrib/admin
parentc9e3b9949cd55f090591fbdc4a114fcb8368b6d9 (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.py6
-rw-r--r--django/contrib/admin/options.py18
-rw-r--r--django/contrib/admin/views/main.py6
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]