Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
53ff0969
Kaydet (Commit)
53ff0969
authored
Agu 07, 2014
tarafından
Simon Charette
Kaydeden (comit)
Tim Graham
Agu 20, 2014
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Prevented data leakage in contrib.admin via query string manipulation.
This is a security fix. Disclosure following shortly.
üst
5307ce56
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
115 additions
and
7 deletions
+115
-7
exceptions.py
django/contrib/admin/exceptions.py
+5
-0
options.py
django/contrib/admin/options.py
+24
-2
main.py
django/contrib/admin/views/main.py
+7
-2
exceptions.txt
docs/ref/exceptions.txt
+1
-0
1.4.14.txt
docs/releases/1.4.14.txt
+15
-0
1.5.9.txt
docs/releases/1.5.9.txt
+15
-0
1.6.6.txt
docs/releases/1.6.6.txt
+15
-0
tests.py
tests/admin_views/tests.py
+33
-3
No files found.
django/contrib/admin/exceptions.py
Dosyayı görüntüle @
53ff0969
...
@@ -4,3 +4,8 @@ from django.core.exceptions import SuspiciousOperation
...
@@ -4,3 +4,8 @@ from django.core.exceptions import SuspiciousOperation
class
DisallowedModelAdminLookup
(
SuspiciousOperation
):
class
DisallowedModelAdminLookup
(
SuspiciousOperation
):
"""Invalid filter was passed to admin view via URL querystring"""
"""Invalid filter was passed to admin view via URL querystring"""
pass
pass
class
DisallowedModelAdminToField
(
SuspiciousOperation
):
"""Invalid to_field was passed to admin view via URL query string"""
pass
django/contrib/admin/options.py
Dosyayı görüntüle @
53ff0969
...
@@ -11,6 +11,7 @@ from django.contrib.admin import widgets, helpers
...
@@ -11,6 +11,7 @@ from django.contrib.admin import widgets, helpers
from
django.contrib.admin
import
validation
from
django.contrib.admin
import
validation
from
django.contrib.admin.checks
import
(
BaseModelAdminChecks
,
ModelAdminChecks
,
from
django.contrib.admin.checks
import
(
BaseModelAdminChecks
,
ModelAdminChecks
,
InlineModelAdminChecks
)
InlineModelAdminChecks
)
from
django.contrib.admin.exceptions
import
DisallowedModelAdminToField
from
django.contrib.admin.utils
import
(
quote
,
unquote
,
flatten_fieldsets
,
from
django.contrib.admin.utils
import
(
quote
,
unquote
,
flatten_fieldsets
,
get_deleted_objects
,
model_format_dict
,
NestedObjects
,
get_deleted_objects
,
model_format_dict
,
NestedObjects
,
lookup_needs_distinct
)
lookup_needs_distinct
)
...
@@ -434,6 +435,24 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
...
@@ -434,6 +435,24 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
valid_lookups
.
append
(
filter_item
)
valid_lookups
.
append
(
filter_item
)
return
clean_lookup
in
valid_lookups
return
clean_lookup
in
valid_lookups
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
in
related_object
.
field
.
foreign_related_fields
):
return
True
return
False
def
has_add_permission
(
self
,
request
):
def
has_add_permission
(
self
,
request
):
"""
"""
Returns True if the given request has permission to add an object.
Returns True if the given request has permission to add an object.
...
@@ -1337,6 +1356,10 @@ class ModelAdmin(BaseModelAdmin):
...
@@ -1337,6 +1356,10 @@ class ModelAdmin(BaseModelAdmin):
@transaction.atomic
@transaction.atomic
def
changeform_view
(
self
,
request
,
object_id
=
None
,
form_url
=
''
,
extra_context
=
None
):
def
changeform_view
(
self
,
request
,
object_id
=
None
,
form_url
=
''
,
extra_context
=
None
):
to_field
=
request
.
POST
.
get
(
TO_FIELD_VAR
,
request
.
GET
.
get
(
TO_FIELD_VAR
))
if
to_field
and
not
self
.
to_field_allowed
(
request
,
to_field
):
raise
DisallowedModelAdminToField
(
"The field
%
s cannot be referenced."
%
to_field
)
model
=
self
.
model
model
=
self
.
model
opts
=
model
.
_meta
opts
=
model
.
_meta
add
=
object_id
is
None
add
=
object_id
is
None
...
@@ -1409,8 +1432,7 @@ class ModelAdmin(BaseModelAdmin):
...
@@ -1409,8 +1432,7 @@ class ModelAdmin(BaseModelAdmin):
original
=
obj
,
original
=
obj
,
is_popup
=
(
IS_POPUP_VAR
in
request
.
POST
or
is_popup
=
(
IS_POPUP_VAR
in
request
.
POST
or
IS_POPUP_VAR
in
request
.
GET
),
IS_POPUP_VAR
in
request
.
GET
),
to_field
=
request
.
POST
.
get
(
TO_FIELD_VAR
,
to_field
=
to_field
,
request
.
GET
.
get
(
TO_FIELD_VAR
)),
media
=
media
,
media
=
media
,
inline_admin_formsets
=
inline_formsets
,
inline_admin_formsets
=
inline_formsets
,
errors
=
helpers
.
AdminErrorList
(
form
,
formsets
),
errors
=
helpers
.
AdminErrorList
(
form
,
formsets
),
...
...
django/contrib/admin/views/main.py
Dosyayı görüntüle @
53ff0969
...
@@ -12,7 +12,9 @@ from django.utils.translation import ugettext, ugettext_lazy
...
@@ -12,7 +12,9 @@ from django.utils.translation import ugettext, ugettext_lazy
from
django.utils.http
import
urlencode
from
django.utils.http
import
urlencode
from
django.contrib.admin
import
FieldListFilter
from
django.contrib.admin
import
FieldListFilter
from
django.contrib.admin.exceptions
import
DisallowedModelAdminLookup
from
django.contrib.admin.exceptions
import
(
DisallowedModelAdminLookup
,
DisallowedModelAdminToField
,
)
from
django.contrib.admin.options
import
IncorrectLookupParameters
,
IS_POPUP_VAR
,
TO_FIELD_VAR
from
django.contrib.admin.options
import
IncorrectLookupParameters
,
IS_POPUP_VAR
,
TO_FIELD_VAR
from
django.contrib.admin.utils
import
(
quote
,
get_fields_from_path
,
from
django.contrib.admin.utils
import
(
quote
,
get_fields_from_path
,
lookup_needs_distinct
,
prepare_lookup_value
)
lookup_needs_distinct
,
prepare_lookup_value
)
...
@@ -58,7 +60,10 @@ class ChangeList(object):
...
@@ -58,7 +60,10 @@ class ChangeList(object):
self
.
page_num
=
0
self
.
page_num
=
0
self
.
show_all
=
ALL_VAR
in
request
.
GET
self
.
show_all
=
ALL_VAR
in
request
.
GET
self
.
is_popup
=
IS_POPUP_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
())
self
.
params
=
dict
(
request
.
GET
.
items
())
if
PAGE_VAR
in
self
.
params
:
if
PAGE_VAR
in
self
.
params
:
del
self
.
params
[
PAGE_VAR
]
del
self
.
params
[
PAGE_VAR
]
...
...
docs/ref/exceptions.txt
Dosyayı görüntüle @
53ff0969
...
@@ -56,6 +56,7 @@ SuspiciousOperation
...
@@ -56,6 +56,7 @@ SuspiciousOperation
* DisallowedHost
* DisallowedHost
* DisallowedModelAdminLookup
* DisallowedModelAdminLookup
* DisallowedModelAdminToField
* DisallowedRedirect
* DisallowedRedirect
* InvalidSessionKey
* InvalidSessionKey
* SuspiciousFileOperation
* SuspiciousFileOperation
...
...
docs/releases/1.4.14.txt
Dosyayı görüntüle @
53ff0969
...
@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
...
@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
requests without an intervening logout could result in the prior user's session
requests without an intervening logout could result in the prior user's session
being co-opted by the subsequent user. The middleware now logs the user out on
being co-opted by the subsequent user. The middleware now logs the user out on
a failed login attempt.
a failed login attempt.
Data leakage via query string manipulation in ``contrib.admin``
===============================================================
In older versions of Django it was possible to reveal any field's data by
modifying the "popup" and "to_field" parameters of the query string on an admin
change form page. For example, requesting a URL like
``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed
viewing the password hash of each user. While the admin requires users to have
permissions to view the change form pages in the first place, this could leak
data if you rely on users having access to view only certain fields on a model.
To address the issue, an exception will now be raised if a ``to_field`` value
that isn't a related field to a model that has been registered with the admin
is specified.
docs/releases/1.5.9.txt
Dosyayı görüntüle @
53ff0969
...
@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
...
@@ -47,3 +47,18 @@ and the ``RemoteUserBackend``, a change to the ``REMOTE_USER`` header between
requests without an intervening logout could result in the prior user's session
requests without an intervening logout could result in the prior user's session
being co-opted by the subsequent user. The middleware now logs the user out on
being co-opted by the subsequent user. The middleware now logs the user out on
a failed login attempt.
a failed login attempt.
Data leakage via query string manipulation in ``contrib.admin``
===============================================================
In older versions of Django it was possible to reveal any field's data by
modifying the "popup" and "to_field" parameters of the query string on an admin
change form page. For example, requesting a URL like
``/admin/auth/user/?pop=1&t=password`` and viewing the page's HTML allowed
viewing the password hash of each user. While the admin requires users to have
permissions to view the change form pages in the first place, this could leak
data if you rely on users having access to view only certain fields on a model.
To address the issue, an exception will now be raised if a ``to_field`` value
that isn't a related field to a model that has been registered with the admin
is specified.
docs/releases/1.6.6.txt
Dosyayı görüntüle @
53ff0969
...
@@ -48,6 +48,21 @@ requests without an intervening logout could result in the prior user's session
...
@@ -48,6 +48,21 @@ requests without an intervening logout could result in the prior user's session
being co-opted by the subsequent user. The middleware now logs the user out on
being co-opted by the subsequent user. The middleware now logs the user out on
a failed login attempt.
a failed login attempt.
Data leakage via query string manipulation in ``contrib.admin``
===============================================================
In older versions of Django it was possible to reveal any field's data by
modifying the "popup" and "to_field" parameters of the query string on an admin
change form page. For example, requesting a URL like
``/admin/auth/user/?_popup=1&t=password`` and viewing the page's HTML allowed
viewing the password hash of each user. While the admin requires users to have
permissions to view the change form pages in the first place, this could leak
data if you rely on users having access to view only certain fields on a model.
To address the issue, an exception will now be raised if a ``to_field`` value
that isn't a related field to a model that has been registered with the admin
is specified.
Bugfixes
Bugfixes
========
========
...
...
tests/admin_views/tests.py
Dosyayı görüntüle @
53ff0969
...
@@ -18,6 +18,7 @@ from django.contrib.auth import get_permission_codename
...
@@ -18,6 +18,7 @@ from django.contrib.auth import get_permission_codename
from
django.contrib.admin
import
ModelAdmin
from
django.contrib.admin
import
ModelAdmin
from
django.contrib.admin.helpers
import
ACTION_CHECKBOX_NAME
from
django.contrib.admin.helpers
import
ACTION_CHECKBOX_NAME
from
django.contrib.admin.models
import
LogEntry
,
DELETION
from
django.contrib.admin.models
import
LogEntry
,
DELETION
from
django.contrib.admin.options
import
TO_FIELD_VAR
from
django.contrib.admin.templatetags.admin_static
import
static
from
django.contrib.admin.templatetags.admin_static
import
static
from
django.contrib.admin.templatetags.admin_urls
import
add_preserved_filters
from
django.contrib.admin.templatetags.admin_urls
import
add_preserved_filters
from
django.contrib.admin.tests
import
AdminSeleniumWebDriverTestCase
from
django.contrib.admin.tests
import
AdminSeleniumWebDriverTestCase
...
@@ -598,6 +599,36 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
...
@@ -598,6 +599,36 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
response
=
self
.
client
.
get
(
"/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=
%
d"
%
e1
.
pk
)
response
=
self
.
client
.
get
(
"/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=
%
d"
%
e1
.
pk
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_disallowed_to_field
(
self
):
with
patch_logger
(
'django.security.DisallowedModelAdminToField'
,
'error'
)
as
calls
:
response
=
self
.
client
.
get
(
"/test_admin/admin/admin_views/section/"
,
{
TO_FIELD_VAR
:
'missing_field'
})
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
len
(
calls
),
1
)
# Specifying a field that is not refered by any other model registered
# to this admin site should raise an exception.
with
patch_logger
(
'django.security.DisallowedModelAdminToField'
,
'error'
)
as
calls
:
response
=
self
.
client
.
get
(
"/test_admin/admin/admin_views/section/"
,
{
TO_FIELD_VAR
:
'name'
})
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
len
(
calls
),
1
)
# Specifying a field referenced by another model should be allowed.
response
=
self
.
client
.
get
(
"/test_admin/admin/admin_views/section/"
,
{
TO_FIELD_VAR
:
'id'
})
self
.
assertEqual
(
response
.
status_code
,
200
)
# We also want to prevent the add and change view from leaking a
# disallowed field value.
with
patch_logger
(
'django.security.DisallowedModelAdminToField'
,
'error'
)
as
calls
:
response
=
self
.
client
.
post
(
"/test_admin/admin/admin_views/section/add/"
,
{
TO_FIELD_VAR
:
'name'
})
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
len
(
calls
),
1
)
section
=
Section
.
objects
.
create
()
with
patch_logger
(
'django.security.DisallowedModelAdminToField'
,
'error'
)
as
calls
:
response
=
self
.
client
.
post
(
"/test_admin/admin/admin_views/section/
%
d/"
%
section
.
pk
,
{
TO_FIELD_VAR
:
'name'
})
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
len
(
calls
),
1
)
def
test_allowed_filtering_15103
(
self
):
def
test_allowed_filtering_15103
(
self
):
"""
"""
Regressions test for ticket 15103 - filtering on fields defined in a
Regressions test for ticket 15103 - filtering on fields defined in a
...
@@ -2378,10 +2409,9 @@ class AdminSearchTest(TestCase):
...
@@ -2378,10 +2409,9 @@ class AdminSearchTest(TestCase):
"""Ensure that the to_field GET parameter is preserved when a search
"""Ensure that the to_field GET parameter is preserved when a search
is performed. Refs #10918.
is performed. Refs #10918.
"""
"""
from
django.contrib.admin.views.main
import
TO_FIELD_VAR
response
=
self
.
client
.
get
(
'/test_admin/admin/auth/user/?q=joe&
%
s=id'
%
TO_FIELD_VAR
)
response
=
self
.
client
.
get
(
'/test_admin/admin/auth/user/?q=joe&
%
s=username'
%
TO_FIELD_VAR
)
self
.
assertContains
(
response
,
"
\n
1 user
\n
"
)
self
.
assertContains
(
response
,
"
\n
1 user
\n
"
)
self
.
assertContains
(
response
,
'<input type="hidden" name="
_to_field" value="username"/>'
,
html
=
True
)
self
.
assertContains
(
response
,
'<input type="hidden" name="
%
s" value="id"/>'
%
TO_FIELD_VAR
,
html
=
True
)
def
test_exact_matches
(
self
):
def
test_exact_matches
(
self
):
response
=
self
.
client
.
get
(
'/test_admin/admin/admin_views/recommendation/?q=bar'
)
response
=
self
.
client
.
get
(
'/test_admin/admin/admin_views/recommendation/?q=bar'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment