[Python-modules-commits] r15619 - in packages/python-django/branches/squeeze/debian (6 files)
hertzog at users.alioth.debian.org
hertzog at users.alioth.debian.org
Sat Feb 12 08:59:04 UTC 2011
Date: Saturday, February 12, 2011 @ 08:59:02
Author: hertzog
Revision: 15619
* Stable security upload:
http://www.djangoproject.com/weblog/2011/feb/08/security/
* Apply/backport the 3 security patches:
- debian/patches/10_fix_csrf_ajax.diff
- debian/patches/11_fix_admin_file_widget.diff
- debian/patches/12_fix_file_session_backend.diff
* Re-add dropped test for 09_fix_dos_password_reset.diff. Thanks to
Jamie Strandboge <jamie at ubuntu.com>. Closes: #610447
Added:
packages/python-django/branches/squeeze/debian/patches/10_fix_csrf_ajax.diff
packages/python-django/branches/squeeze/debian/patches/11_fix_admin_file_widget.diff
packages/python-django/branches/squeeze/debian/patches/12_fix_file_session_backend.diff
Modified:
packages/python-django/branches/squeeze/debian/changelog
packages/python-django/branches/squeeze/debian/patches/09_fix_dos_password_reset.diff
packages/python-django/branches/squeeze/debian/patches/series
Modified: packages/python-django/branches/squeeze/debian/changelog
===================================================================
--- packages/python-django/branches/squeeze/debian/changelog 2011-02-12 08:52:46 UTC (rev 15618)
+++ packages/python-django/branches/squeeze/debian/changelog 2011-02-12 08:59:02 UTC (rev 15619)
@@ -1,3 +1,16 @@
+python-django (1.2.3-4) stable-security; urgency=low
+
+ * Stable security upload:
+ http://www.djangoproject.com/weblog/2011/feb/08/security/
+ * Apply/backport the 3 security patches:
+ - debian/patches/10_fix_csrf_ajax.diff
+ - debian/patches/11_fix_admin_file_widget.diff
+ - debian/patches/12_fix_file_session_backend.diff
+ * Re-add dropped test for 09_fix_dos_password_reset.diff. Thanks to
+ Jamie Strandboge <jamie at ubuntu.com>. Closes: #610447
+
+ -- Raphaël Hertzog <hertzog at debian.org> Sat, 12 Feb 2011 09:17:26 +0100
+
python-django (1.2.3-3) testing; urgency=high
* Squeeze upload with security fixes only:
Modified: packages/python-django/branches/squeeze/debian/patches/09_fix_dos_password_reset.diff
===================================================================
--- packages/python-django/branches/squeeze/debian/patches/09_fix_dos_password_reset.diff 2011-02-12 08:52:46 UTC (rev 15618)
+++ packages/python-django/branches/squeeze/debian/patches/09_fix_dos_password_reset.diff 2011-02-12 08:59:02 UTC (rev 15619)
@@ -1,7 +1,6 @@
-Description: Fix denial-of-service attack in password-reset mechanism
- http://www.djangoproject.com/weblog/2010/dec/22/security/
-Origin: upstream, http://code.djangoproject.com/changeset/15034
-
+Description: Fix denial-of-service attack in password-reset mechanism
+Origin: upstream, http://code.djangoproject.com/changeset/15034
+Bug: http://www.djangoproject.com/weblog/2010/dec/22/security/
--- a/django/contrib/auth/urls.py
+++ b/django/contrib/auth/urls.py
@@ -1,4 +1,4 @@
@@ -36,3 +35,15 @@
return int(s, 36)
def int_to_base36(i):
+--- a/django/contrib/auth/tests/tokens.py 2011-01-18 08:57:34.000000000 -0600
++++ b/django/contrib/auth/tests/tokens.py 2011-01-18 08:57:40.000000000 -0600
+@@ -34,4 +34,9 @@
+ >>> p2.check_token(u, tk1)
+ False
+
++This will put a 14-digit base36 timestamp into the token, which is too large.
++>>> tk1 = p0._make_token_with_timestamp(u, 175455491841851871349)
++>>> p0.check_token(u, tk1)
++False
++
+ """
Added: packages/python-django/branches/squeeze/debian/patches/10_fix_csrf_ajax.diff
===================================================================
--- packages/python-django/branches/squeeze/debian/patches/10_fix_csrf_ajax.diff (rev 0)
+++ packages/python-django/branches/squeeze/debian/patches/10_fix_csrf_ajax.diff 2011-02-12 08:59:02 UTC (rev 15619)
@@ -0,0 +1,163 @@
+Description: Fix flaw in CSRF handling
+Origin: backport, http://code.djangoproject.com/changeset/15465
+Bug: http://www.djangoproject.com/weblog/2011/feb/08/security/
+
+--- a/django/middleware/csrf.py
++++ b/django/middleware/csrf.py
+@@ -85,6 +85,7 @@ class CsrfViewMiddleware(object):
+ tag.
+ """
+ def process_view(self, request, callback, callback_args, callback_kwargs):
++
+ if getattr(request, 'csrf_processing_done', False):
+ return None
+
+@@ -126,31 +127,6 @@ class CsrfViewMiddleware(object):
+ # any branches that call reject()
+ return accept()
+
+- if request.is_ajax():
+- # .is_ajax() is based on the presence of X-Requested-With. In
+- # the context of a browser, this can only be sent if using
+- # XmlHttpRequest. Browsers implement careful policies for
+- # XmlHttpRequest:
+- #
+- # * Normally, only same-domain requests are allowed.
+- #
+- # * Some browsers (e.g. Firefox 3.5 and later) relax this
+- # carefully:
+- #
+- # * if it is a 'simple' GET or POST request (which can
+- # include no custom headers), it is allowed to be cross
+- # domain. These requests will not be recognized as AJAX.
+- #
+- # * if a 'preflight' check with the server confirms that the
+- # server is expecting and allows the request, cross domain
+- # requests even with custom headers are allowed. These
+- # requests will be recognized as AJAX, but can only get
+- # through when the developer has specifically opted in to
+- # allowing the cross-domain POST request.
+- #
+- # So in all cases, it is safe to allow these requests through.
+- return accept()
+-
+ if request.is_secure():
+ # Strict referer checking for HTTPS
+ referer = request.META.get('HTTP_REFERER')
+@@ -181,7 +157,11 @@ class CsrfViewMiddleware(object):
+ csrf_token = request.META["CSRF_COOKIE"]
+
+ # check incoming token
+- request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
++ request_csrf_token = request.POST.get('csrfmiddlewaretoken', "")
++ if request_csrf_token == "":
++ # Fall back to X-CSRFToken, to make things easier for AJAX
++ request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
++
+ if request_csrf_token != csrf_token:
+ if cookie_is_new:
+ # probably a problem setting the CSRF cookie
+--- a/tests/regressiontests/csrf_tests/tests.py
++++ b/tests/regressiontests/csrf_tests/tests.py
+@@ -275,12 +275,12 @@ class CsrfMiddlewareTest(TestCase):
+ req2 = CsrfMiddleware().process_view(req, csrf_exempt(post_form_view), (), {})
+ self.assertEquals(None, req2)
+
+- def test_ajax_exemption(self):
++ def test_csrf_token_in_header(self):
+ """
+- Check that AJAX requests are automatically exempted.
++ Check that we can pass in the token in a header instead of in the form
+ """
+ req = self._get_POST_csrf_cookie_request()
+- req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
++ req.META['HTTP_X_CSRFTOKEN'] = self._csrf_id
+ req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
+ self.assertEquals(None, req2)
+
+--- a/docs/ref/contrib/csrf.txt
++++ b/docs/ref/contrib/csrf.txt
+@@ -81,6 +81,47 @@ The utility script ``extras/csrf_migrati
+ finding of code and templates that may need to be upgraded. It contains full
+ help on how to use it.
+
++AJAX
++----
++
++While the above method can be used for AJAX POST requests, it has some
++inconveniences: you have to remember to pass the CSRF token in as POST data with
++every POST request. For this reason, there is an alternative method: on each
++XMLHttpRequest, set a custom `X-CSRFToken` header to the value of the CSRF
++token. This is often easier, because many javascript frameworks provide hooks
++that allow headers to be set on every request. In jQuery, you can use the
++``beforeSend`` hook as follows:
++
++.. code-block:: javascript
++
++ $.ajaxSetup({
++ beforeSend: function(xhr, settings) {
++ function getCookie(name) {
++ var cookieValue = null;
++ if (document.cookie && document.cookie != '') {
++ var cookies = document.cookie.split(';');
++ for (var i = 0; i < cookies.length; i++) {
++ var cookie = jQuery.trim(cookies[i]);
++ // Does this cookie string begin with the name we want?
++ if (cookie.substring(0, name.length + 1) == (name + '=')) {
++ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
++ break;
++ }
++ }
++ }
++ return cookieValue;
++ }
++ if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
++ // Only send the token to relative URLs i.e. locally.
++ xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
++ }
++ }
++ });
++
++Adding this to a javascript file that is included on your site will ensure that
++AJAX POST requests that are made via jQuery will not be caught by the CSRF
++protection.
++
+ The decorator method
+ --------------------
+
+@@ -262,10 +303,6 @@ in the same module. These disable the v
+ (``CsrfResponseMiddleware``) respectively. They can be used individually if
+ required.
+
+-You don't have to worry about doing this for most AJAX views. Any request sent
+-with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the `How
+-it works`_ section.)
+-
+ Subdomains
+ ----------
+
+@@ -343,24 +380,6 @@ request ought to be harmless.
+ response, and only pages that are served as 'text/html' or
+ 'application/xml+xhtml' are modified.
+
+-AJAX
+-----
+-
+-The middleware tries to be smart about requests that come in via AJAX. Most
+-modern JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP
+-header; these requests are detected and automatically *not* handled by this
+-middleware. We can do this safely because, in the context of a browser, the
+-header can only be added by using ``XMLHttpRequest``, and browsers already
+-implement a same-domain policy for ``XMLHttpRequest``.
+-
+-For the more recent browsers that relax this same-domain policy, custom headers
+-like "X-Requested-With" are only allowed after the browser has done a
+-'preflight' check to the server to see if the cross-domain request is allowed,
+-using a strictly 'opt in' mechanism, so the exception for AJAX is still safeâif
+-the developer has specifically opted in to allowing cross-site AJAX POST
+-requests on a specific URL, they obviously don't want the middleware to disallow
+-exactly that.
+-
+ .. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
+
+ Caching
Added: packages/python-django/branches/squeeze/debian/patches/11_fix_admin_file_widget.diff
===================================================================
--- packages/python-django/branches/squeeze/debian/patches/11_fix_admin_file_widget.diff (rev 0)
+++ packages/python-django/branches/squeeze/debian/patches/11_fix_admin_file_widget.diff 2011-02-12 08:59:02 UTC (rev 15619)
@@ -0,0 +1,37 @@
+Description: Fix potential XSS in file field rendering
+Origin: upstream, http://code.djangoproject.com/changeset/15472
+Bug: http://www.djangoproject.com/weblog/2011/feb/08/security/
+
+--- a/django/contrib/admin/widgets.py
++++ b/django/contrib/admin/widgets.py
+@@ -96,7 +96,7 @@ class AdminFileWidget(forms.FileInput):
+ output = []
+ if value and hasattr(value, "url"):
+ output.append('%s <a target="_blank" href="%s">%s</a> <br />%s ' % \
+- (_('Currently:'), value.url, value, _('Change:')))
++ (_('Currently:'), escape(value.url), escape(value), _('Change:')))
+ output.append(super(AdminFileWidget, self).render(name, value, attrs))
+ return mark_safe(u''.join(output))
+
+--- a/tests/regressiontests/admin_widgets/tests.py
++++ b/tests/regressiontests/admin_widgets/tests.py
+@@ -151,3 +151,19 @@ class AdminForeignKeyRawIdWidget(DjangoT
+ post_data)
+ self.assertContains(response,
+ 'Select a valid choice. That choice is not one of the available choices.')
++
++class AdminFileWidgetTest(DjangoTestCase):
++ def test_render_escapes_html(self):
++ class StrangeFieldFile(object):
++ url = "something?chapter=1§=2©=3&lang=en"
++
++ def __unicode__(self):
++ return u'''something<div onclick="alert('oops')">.jpg'''
++
++ widget = AdminFileWidget()
++ field = StrangeFieldFile()
++ output = widget.render('myfile', field)
++ self.assertFalse(field.url in output)
++ self.assertTrue(u'href="something?chapter=1&sect=2&copy=3&lang=en"' in output)
++ self.assertFalse(unicode(field) in output)
++ self.assertTrue(u'something<div onclick="alert('oops')">.jpg' in output)
Added: packages/python-django/branches/squeeze/debian/patches/12_fix_file_session_backend.diff
===================================================================
--- packages/python-django/branches/squeeze/debian/patches/12_fix_file_session_backend.diff (rev 0)
+++ packages/python-django/branches/squeeze/debian/patches/12_fix_file_session_backend.diff 2011-02-12 08:59:02 UTC (rev 15619)
@@ -0,0 +1,45 @@
+Description: Fix directory-traversal vulnerability on Windows
+Origin: upstream, http://code.djangoproject.com/changeset/15468
+Bug: http://www.djangoproject.com/weblog/2011/feb/08/security/
+
+Index: Django/django/contrib/sessions/tests.py
+===================================================================
+--- Django/django/contrib/sessions/tests.py (revision 9934)
++++ Django/django/contrib/sessions/tests.py (revision 15468)
+@@ -130,4 +130,15 @@
+ >>> file_session.save()
+
++# Ensure we don't allow directory traversal
++>>> FileSession("a/b/c").load()
++Traceback (innermost last):
++ ...
++SuspiciousOperation: Invalid characters in session key
++
++>>> FileSession("a\\b\\c").load()
++Traceback (innermost last):
++ ...
++SuspiciousOperation: Invalid characters in session key
++
+ # Make sure the file backend checks for a good storage dir
+ >>> settings.SESSION_FILE_PATH = "/if/this/directory/exists/you/have/a/weird/computer"
+Index: Django/django/contrib/sessions/backends/file.py
+===================================================================
+--- Django/django/contrib/sessions/backends/file.py (revision 8812)
++++ Django/django/contrib/sessions/backends/file.py (revision 15468)
+@@ -27,4 +27,6 @@
+ super(SessionStore, self).__init__(session_key)
+
++ VALID_KEY_CHARS = set("abcdef0123456789")
++
+ def _key_to_file(self, session_key=None):
+ """
+@@ -37,7 +39,7 @@
+ # should always be md5s, so they should never contain directory
+ # components.
+- if os.path.sep in session_key:
++ if not set(session_key).issubset(self.VALID_KEY_CHARS):
+ raise SuspiciousOperation(
+- "Invalid characters (directory components) in session key")
++ "Invalid characters in session key")
+
+ return os.path.join(self.storage_path, self.file_prefix + session_key)
Modified: packages/python-django/branches/squeeze/debian/patches/series
===================================================================
--- packages/python-django/branches/squeeze/debian/patches/series 2011-02-12 08:52:46 UTC (rev 15618)
+++ packages/python-django/branches/squeeze/debian/patches/series 2011-02-12 08:59:02 UTC (rev 15619)
@@ -6,3 +6,6 @@
07_disable_url_verify_model_tests.diff
08_fix_info_leakage.diff
09_fix_dos_password_reset.diff
+10_fix_csrf_ajax.diff
+11_fix_admin_file_widget.diff
+12_fix_file_session_backend.diff
More information about the Python-modules-commits
mailing list