diff options
| author | Tim Graham <timograham@gmail.com> | 2013-08-19 09:35:26 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-08-22 17:49:11 -0400 |
| commit | 616a4d385a79d6809b618dcc8bcbda05b032d5fc (patch) | |
| tree | ee40caee925ddc8ab4823edb2611945ae66443ae /docs | |
| parent | 1b236048b9a915296dc13081fad7bb75d0ff1f4d (diff) | |
[1.5.x] Fixed #20922 -- Allowed customizing the serializer used by contrib.sessions
Added settings.SESSION_SERIALIZER which is the import path of a serializer
to use for sessions.
Thanks apollo13, carljm, shaib, akaariai, charettes, and dstufft for reviews.
Backport of b0ce6fe656 from master
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/settings.txt | 28 | ||||
| -rw-r--r-- | docs/topics/http/sessions.txt | 88 |
2 files changed, 108 insertions, 8 deletions
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 64f269a553..fc3f33904c 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1444,6 +1444,8 @@ Sets the minimum message level that will be recorded by the messages framework. See the :doc:`messages documentation </ref/contrib/messages>` for more details. +.. setting:: MESSAGE_STORAGE + MESSAGE_STORAGE --------------- @@ -1817,7 +1819,7 @@ SESSION_ENGINE Default: ``django.contrib.sessions.backends.db`` -Controls where Django stores session data. Valid values are: +Controls where Django stores session data. Included engines are: * ``'django.contrib.sessions.backends.db'`` * ``'django.contrib.sessions.backends.file'`` @@ -1859,6 +1861,30 @@ Default: ``False`` Whether to save the session data on every request. See :doc:`/topics/http/sessions`. +.. setting:: SESSION_SERIALIZER + +SESSION_SERIALIZER +------------------ + +.. versionadded:: 1.5.3 + +Default: ``'django.contrib.sessions.serializers.PickleSerializer'`` + +Full import path of a serializer class to use for serializing session data. +Included serializers are: + +* ``'django.contrib.sessions.serializers.PickleSerializer'`` +* ``'django.contrib.sessions.serializers.JSONSerializer'`` + +See :ref:`session_serialization` for details, including a warning regarding +possible remote code execution when using +:class:`~django.contrib.sessions.serializers.PickleSerializer`. + +In Django 1.5.3, the default in newly created projects using +:djadmin:`django-admin.py startproject <startproject>` is +:class:`django.contrib.sessions.serializers.JSONSerializer`, and the global +default will switch to this class in Django 1.6. + .. setting:: SHORT_DATE_FORMAT SHORT_DATE_FORMAT diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index 320f26b384..d430a532df 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -124,8 +124,9 @@ and the :setting:`SECRET_KEY` setting. .. warning:: - **If the SECRET_KEY is not kept secret, this can lead to arbitrary remote - code execution.** + **If the SECRET_KEY is not kept secret and you are using the** + :class:`~django.contrib.sessions.serializers.PickleSerializer`, **this can + lead to arbitrary remote code execution.** An attacker in possession of the :setting:`SECRET_KEY` can not only generate falsified session data, which your site will trust, but also @@ -252,7 +253,9 @@ You can edit it multiple times. in 5 minutes. * If ``value`` is a ``datetime`` or ``timedelta`` object, the - session will expire at that specific date/time. + session will expire at that specific date/time. Note that ``datetime`` + and ``timedelta`` values are only serializable if you are using the + :class:`~django.contrib.sessions.serializers.PickleSerializer`. * If ``value`` is ``0``, the user's session cookie will expire when the user's Web browser is closed. @@ -299,6 +302,73 @@ You can edit it multiple times. Removes expired sessions from the session store. This class method is called by :djadmin:`clearsessions`. +.. _session_serialization: + +Session serialization +--------------------- + +.. versionadded:: 1.5.3 + +Before version 1.6, Django defaulted to using :mod:`pickle` to serialize +session data before storing it in the backend. If you're using the :ref:`signed +cookie session backend<cookie-session-backend>` and :setting:`SECRET_KEY` is +known by an attacker, the attacker could insert a string into his session +which, when unpickled, executes arbitrary code on the server. The technique for +doing so is simple and easily available on the internet. Although the cookie +session storage signs the cookie-stored data to prevent tampering, a +:setting:`SECRET_KEY` leak immediately escalates to a remote code execution +vulnerability. + +This attack can be mitigated by serializing session data using JSON rather +than :mod:`pickle`. To facilitate this, Django 1.5.3 introduced a new setting, +:setting:`SESSION_SERIALIZER`, to customize the session serialization format. +For backwards compatibility, this setting defaults to +using :class:`django.contrib.sessions.serializers.PickleSerializer` in Django +1.5.x, but, for security hardening, defaults to +:class:`django.contrib.sessions.serializers.JSONSerializer` in Django 1.6. If +you upgrade and switch from pickle to JSON, sessions created before the upgrade +will be lost. Even with the caveats described in :ref:`custom-serializers`, we +highly recommend using JSON serialization *especially if you are using the +cookie backend*. + +Bundled Serializers +^^^^^^^^^^^^^^^^^^^ + +.. class:: serializers.JSONSerializer + + A wrapper around the JSON serializer from :mod:`django.core.signing`. Can + only serialize basic data types. See the :ref:`custom-serializers` section + for more details. + +.. class:: serializers.PickleSerializer + + Supports arbitrary Python objects, but, as described above, can lead to a + remote code execution vulnerability if :setting:`SECRET_KEY` becomes known + by an attacker. + +.. _custom-serializers: + +Write Your Own Serializer +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Note that unlike :class:`~django.contrib.sessions.serializers.PickleSerializer`, +the :class:`~django.contrib.sessions.serializers.JSONSerializer` cannot handle +arbitrary Python data types. As is often the case, there is a trade-off between +convenience and security. If you wish to store more advanced data types +including ``datetime`` and ``Decimal`` in JSON backed sessions, you will need +to write a custom serializer (or convert such values to a JSON serializable +object before storign them in ``request.session``). While serializing these +values is fairly straightforward +(``django.core.serializers.json.DateTimeAwareJSONEncoder`` may +be helpful), writing a decoder that can reliably get back the same thing that +you put in is more fragile. For example, you run the risk of returning a +``datetime`` that was actually a string that just happened to be in the same +format chosen for ``datetime``\s). + +Your serializer class must implement two methods, +``dumps(self, obj)`` and ``loads(self, data)``, to serialize and deserialize +the dictionary of session data, respectively. + Session object guidelines ------------------------- @@ -388,14 +458,15 @@ An API is available to manipulate session data outside of a view:: >>> from django.contrib.sessions.backends.db import SessionStore >>> import datetime >>> s = SessionStore() - >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) + >>> # stored as seconds since epoch since datetimes are not serializable in JSON. + >>> s['last_login'] = 1376587691 >>> s.save() >>> s.session_key '2b1189a188b44ad18c35e113ac6ceead' >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') >>> s['last_login'] - datetime.datetime(2005, 8, 20, 13, 35, 0) + 1376587691 In order to prevent session fixation attacks, sessions keys that don't exist are regenerated:: @@ -634,8 +705,11 @@ that is, if any of its dictionary values have been assigned or deleted. Technical details ================= -* The session dictionary should accept any pickleable Python object. See - the :mod:`pickle` module for more information. +* The session dictionary accepts any :mod:`json` serializable value when using + :class:`~django.contrib.sessions.serializers.JSONSerializer` or any + pickleable Python object when using + :class:`~django.contrib.sessions.serializers.PickleSerializer`. See the + :mod:`pickle` module for more information. * Session data is stored in a database table named ``django_session`` . |
