From 4d975b4f882eb2a68da02e069aa1debb99073497 Mon Sep 17 00:00:00 2001 From: Paul McMillan Date: Mon, 21 Nov 2011 22:03:03 +0000 Subject: [PATCH] Fixed #16847. Session Cookies now default to httponly = True. git-svn-id: http://code.djangoproject.com/svn/django/trunk@17135 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/conf/global_settings.py | 2 +- django/contrib/sessions/tests.py | 25 +++++++++++++++++++++++-- docs/ref/request-response.txt | 8 ++++++-- docs/releases/1.4.txt | 11 +++++++---- docs/topics/http/sessions.txt | 6 +++--- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 2ef2f63618..0aee63dbc3 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -445,7 +445,7 @@ SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seco SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). SESSION_COOKIE_PATH = '/' # The path of the session cookie. -SESSION_COOKIE_HTTPONLY = False # Whether to use the non-RFC standard httpOnly flag (IE, FF3+, others) +SESSION_COOKIE_HTTPONLY = True # Whether to use the non-RFC standard httpOnly flag (IE, FF3+, others) SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether a user's session cookie expires when the Web browser is closed. SESSION_ENGINE = 'django.contrib.sessions.backends.db' # The module to store session data diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index ce39fef0ad..58d052d67b 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -343,7 +343,8 @@ class SessionMiddlewareTests(unittest.TestCase): # Handle the response through the middleware response = middleware.process_response(request, response) - self.assertTrue(response.cookies[settings.SESSION_COOKIE_NAME]['secure']) + self.assertTrue( + response.cookies[settings.SESSION_COOKIE_NAME]['secure']) @override_settings(SESSION_COOKIE_HTTPONLY=True) def test_httponly_session_cookie(self): @@ -357,7 +358,27 @@ class SessionMiddlewareTests(unittest.TestCase): # Handle the response through the middleware response = middleware.process_response(request, response) - self.assertTrue(response.cookies[settings.SESSION_COOKIE_NAME]['httponly']) + self.assertTrue( + response.cookies[settings.SESSION_COOKIE_NAME]['httponly']) + self.assertIn('httponly', + str(response.cookies[settings.SESSION_COOKIE_NAME])) + + @override_settings(SESSION_COOKIE_HTTPONLY=False) + def test_no_httponly_session_cookie(self): + request = RequestFactory().get('/') + response = HttpResponse('Session test') + middleware = SessionMiddleware() + + # Simulate a request the modifies the session + middleware.process_request(request) + request.session['hello'] = 'world' + + # Handle the response through the middleware + response = middleware.process_response(request, response) + self.assertFalse( + response.cookies[settings.SESSION_COOKIE_NAME]['httponly']) + self.assertNotIn('httponly', + str(response.cookies[settings.SESSION_COOKIE_NAME]['httponly'])) class CookieSessionTests(SessionTestsMixin, TestCase): diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index f0ec7cf237..228b69ebe2 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -638,7 +638,7 @@ Methods Returns ``True`` or ``False`` based on a case-insensitive check for a header with the given name. -.. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False) +.. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True) .. versionchanged:: 1.3 @@ -646,6 +646,10 @@ Methods ``expires``, and the auto-calculation of ``max_age`` in such case was added. The ``httponly`` argument was also added. + .. versionchanged:: 1.4 + + The default value for httponly was changed from ``False`` to ``True``. + Sets a cookie. The parameters are the same as in the :class:`Cookie.Morsel` object in the Python standard library. @@ -673,7 +677,7 @@ Methods .. _HTTPOnly: http://www.owasp.org/index.php/HTTPOnly -.. method:: HttpResponse.set_signed_cookie(key, value='', salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False) +.. method:: HttpResponse.set_signed_cookie(key, value='', salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True) .. versionadded:: 1.4 diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 46527da581..b611626099 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -451,10 +451,10 @@ Minor features Django 1.4 also includes several smaller improvements worth noting: -* A more usable stacktrace in the technical 500 page: frames in the stack - trace which reference Django's code are dimmed out, while frames in user - code are slightly emphasized. This change makes it easier to scan a stacktrace - for issues in user code. +* A more usable stacktrace in the technical 500 page: frames in the + stack trace which reference Django's code are dimmed out, while + frames in user code are slightly emphasized. This change makes it + easier to scan a stacktrace for issues in user code. * :doc:`Tablespace support ` in PostgreSQL. @@ -498,6 +498,9 @@ Django 1.4 also includes several smaller improvements worth noting: * Added the :djadminopt:`--no-location` option to the :djadmin:`makemessages` command. +* Changed the default value for ``httponly`` on session cookies to + ``True`` to help reduce the impact of potential XSS attacks. + .. _backwards-incompatible-changes-1.4: Backwards incompatible changes in 1.4 diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index 2f13c9662a..dcd4ea2c74 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -110,8 +110,8 @@ and the :setting:`SECRET_KEY` setting. .. note:: - It's recommended to set the :setting:`SESSION_COOKIE_HTTPONLY` setting - to ``True`` to prevent tampering of the stored data from JavaScript. + It's recommended to leave the :setting:`SESSION_COOKIE_HTTPONLY` setting + ``True`` to prevent tampering of the stored data from JavaScript. .. warning:: @@ -504,7 +504,7 @@ The domain to use for session cookies. Set this to a string such as SESSION_COOKIE_HTTPONLY ----------------------- -Default: ``False`` +Default: ``True`` Whether to use HTTPOnly flag on the session cookie. If this is set to ``True``, client-side JavaScript will not to be able to access the