Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f68e5a9

Browse files
committed
[1.8.x] Fixed XSS in admin's add/change related popup.
This is a security fix.
1 parent 358ae4a commit f68e5a9

File tree

6 files changed

+60
-6
lines changed

6 files changed

+60
-6
lines changed

django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) {
105105
var selects = django.jQuery(selectsSelector);
106106
selects.find('option').each(function() {
107107
if (this.value == objId) {
108-
this.innerHTML = newRepr;
108+
this.textContent = newRepr;
109109
this.value = newId;
110110
}
111111
});

django/views/debug.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,13 +704,13 @@ def default_urlconf(request):
704704
var s = link.getElementsByTagName('span')[0];
705705
var uarr = String.fromCharCode(0x25b6);
706706
var darr = String.fromCharCode(0x25bc);
707-
s.innerHTML = s.innerHTML == uarr ? darr : uarr;
707+
s.textContent = s.textContent == uarr ? darr : uarr;
708708
return false;
709709
}
710710
function switchPastebinFriendly(link) {
711711
s1 = "Switch to copy-and-paste view";
712712
s2 = "Switch back to interactive view";
713-
link.innerHTML = link.innerHTML.trim() == s1 ? s2: s1;
713+
link.textContent = link.textContent.trim() == s1 ? s2: s1;
714714
toggle('browserTraceback', 'pastebinTraceback');
715715
return false;
716716
}

docs/releases/1.8.14.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@
22
Django 1.8.14 release notes
33
===========================
44

5-
*Under development*
5+
*July 18, 2016*
66

7-
Django 1.8.14 fixes several bugs in 1.8.13.
7+
Django 1.8.14 fixes a security issue and a bug in 1.8.13.
8+
9+
XSS in admin's add/change related popup
10+
=======================================
11+
12+
Unsafe usage of JavaScript's ``Element.innerHTML`` could result in XSS in the
13+
admin's add/change related popup. ``Element.textContent`` is now used to
14+
prevent execution of the data.
15+
16+
The debug view also used ``innerHTML``. Although a security issue wasn't
17+
identified there, out of an abundance of caution it's also updated to use
18+
``textContent``.
819

920
Bugfixes
1021
========

tests/admin_views/admin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class ChapterXtra1Admin(admin.ModelAdmin):
8888

8989
class ArticleAdmin(admin.ModelAdmin):
9090
list_display = ('content', 'date', callable_year, 'model_year',
91-
'modeladmin_year', 'model_year_reversed')
91+
'modeladmin_year', 'model_year_reversed', 'section')
92+
list_editable = ('section',)
9293
list_filter = ('date', 'section')
9394
view_on_site = False
9495
fieldsets = (

tests/admin_views/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616
from django.utils.encoding import python_2_unicode_compatible
1717

1818

19+
@python_2_unicode_compatible
1920
class Section(models.Model):
2021
"""
2122
A simple section that links to articles, to test linking to related items
2223
in admin views.
2324
"""
2425
name = models.CharField(max_length=100)
2526

27+
def __str__(self):
28+
return self.name
29+
2630
@property
2731
def name_property(self):
2832
"""

tests/admin_views/tests.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,6 +4056,44 @@ def test_cancel_delete_related_confirmation(self):
40564056
self.assertEqual(Pizza.objects.count(), 1)
40574057
self.assertEqual(Topping.objects.count(), 2)
40584058

4059+
def test_list_editable_popups(self):
4060+
"""
4061+
list_editable foreign keys have add/change popups.
4062+
"""
4063+
from selenium.webdriver.support.ui import Select
4064+
s1 = Section.objects.create(name='Test section')
4065+
Article.objects.create(
4066+
title='foo',
4067+
content='<p>Middle content</p>',
4068+
date=datetime.datetime(2008, 3, 18, 11, 54, 58),
4069+
section=s1,
4070+
)
4071+
self.admin_login(username='super', password='secret', login_url=reverse('admin:index'))
4072+
self.selenium.get(self.live_server_url + reverse('admin:admin_views_article_changelist'))
4073+
# Change popup
4074+
self.selenium.find_element_by_id('change_id_form-0-section').click()
4075+
self.wait_for_popup()
4076+
self.selenium.switch_to.window(self.selenium.window_handles[-1])
4077+
self.wait_for_text('#content h1', 'Change section')
4078+
name_input = self.selenium.find_element_by_id('id_name')
4079+
name_input.clear()
4080+
name_input.send_keys('<i>edited section</i>')
4081+
self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
4082+
self.selenium.switch_to.window(self.selenium.window_handles[0])
4083+
select = Select(self.selenium.find_element_by_id('id_form-0-section'))
4084+
self.assertEqual(select.first_selected_option.text, '<i>edited section</i>')
4085+
4086+
# Add popup
4087+
self.selenium.find_element_by_id('add_id_form-0-section').click()
4088+
self.wait_for_popup()
4089+
self.selenium.switch_to.window(self.selenium.window_handles[-1])
4090+
self.wait_for_text('#content h1', 'Add section')
4091+
self.selenium.find_element_by_id('id_name').send_keys('new section')
4092+
self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
4093+
self.selenium.switch_to.window(self.selenium.window_handles[0])
4094+
select = Select(self.selenium.find_element_by_id('id_form-0-section'))
4095+
self.assertEqual(select.first_selected_option.text, 'new section')
4096+
40594097
def test_list_editable_raw_id_fields(self):
40604098
parent = ParentWithUUIDPK.objects.create(title='test')
40614099
parent2 = ParentWithUUIDPK.objects.create(title='test2')

0 commit comments

Comments
 (0)