Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #5880 -- Fixed an XSS hole in the admin interface.

 * Escaped text that gets sent after saving the admin foreignkey popup form.
 * Added quotes around the second argument passed to `opener.dismissAddAnotherPopup` to make the function also work when a text field is used as the primary key.
 * Added a `html_unescape` javascript function to unescape the strings passed in to the `dismissAddAnotherPopup` function so that the added choice displays correctly in the dropdown box.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@6691 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 38d972b9ecb01fdb863c686de0b958389bc20220 1 parent 5f8cfe9
Gary Wilson Jr. authored November 18, 2007
14  django/contrib/admin/media/js/admin/RelatedObjectLookups.js
... ...
@@ -1,6 +1,16 @@
1 1
 // Handles related-objects functionality: lookup link for raw_id_admin=True
2 2
 // and Add Another links.
3 3
 
  4
+function html_unescape(text) {
  5
+    // Unescape a string that was escaped using django.utils.html.escape.
  6
+    text = text.replace(/&lt;/g, '<');
  7
+    text = text.replace(/&gt;/g, '>');
  8
+    text = text.replace(/&quot;/g, '"');
  9
+    text = text.replace(/&#39;/g, "'");
  10
+    text = text.replace(/&amp;/g, '&');
  11
+    return text;
  12
+}
  13
+
4 14
 function showRelatedObjectLookupPopup(triggeringLink) {
5 15
     var name = triggeringLink.id.replace(/^lookup_/, '');
6 16
     // IE doesn't like periods in the window name, so convert temporarily.
@@ -42,6 +52,10 @@ function showAddAnotherPopup(triggeringLink) {
42 52
 }
43 53
 
44 54
 function dismissAddAnotherPopup(win, newId, newRepr) {
  55
+    // newId and newRepr are expected to have previously been escaped by
  56
+    // django.utils.html.escape.
  57
+    newId = html_unescape(newId);
  58
+    newRepr = html_unescape(newRepr);
45 59
     var name = win.name.replace(/___/g, '.');
46 60
     var elem = document.getElementById(name);
47 61
     if (elem) {
7  django/contrib/admin/views/main.py
@@ -273,10 +273,9 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
273 273
                     post_url_continue += "?_popup=1"
274 274
                 return HttpResponseRedirect(post_url_continue % pk_value)
275 275
             if "_popup" in request.POST:
276  
-                if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
277  
-                    pk_value = '"%s"' % pk_value.replace('"', '\\"')
278  
-                return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
279  
-                    (pk_value, force_unicode(new_object).replace('"', '\\"')))
  276
+                return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
  277
+                    # escape() calls force_unicode.
  278
+                    (escape(pk_value), escape(new_object)))
280 279
             elif "_addanother" in request.POST:
281 280
                 request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
282 281
                 return HttpResponseRedirect(request.path)

0 notes on commit 38d972b

Please sign in to comment.
Something went wrong with that request. Please try again.