Bert JW Regeer
2016-01-28 00bdaf9d6c544dbfb4cd95c62c0c2706c34d1632
Merge pull request #2299 from mmerickel/backport/2298-1.6

convert csrf tokens to bytes prior to string compare
4 files modified
20 ■■■■■ changed files
CHANGES.txt 7 ●●●●● patch | view | raw | blame | history
pyramid/session.py 3 ●●●● patch | view | raw | blame | history
pyramid/testing.py 3 ●●●● patch | view | raw | blame | history
pyramid/tests/test_session.py 7 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,3 +1,10 @@
unreleased
==========
- Fix an issue with differing CSRF token data types on Python runtimes
  supporting ``hmac.compare_digest``.
  See https://github.com/Pylons/pyramid/pull/2299
1.6 (2016-01-03)
================
pyramid/session.py
@@ -126,7 +126,8 @@
    .. versionadded:: 1.4a2
    """
    supplied_token = request.params.get(token, request.headers.get(header, ""))
    if strings_differ(request.session.get_csrf_token(), supplied_token):
    expected_token = request.session.get_csrf_token()
    if strings_differ(bytes_(expected_token), bytes_(supplied_token)):
        if raises:
            raise BadCSRFToken('check_csrf_token(): Invalid token')
        return False
pyramid/testing.py
@@ -16,6 +16,7 @@
    PY3,
    PYPY,
    class_types,
    text_,
    )
from pyramid.config import Configurator
@@ -273,7 +274,7 @@
        return storage
    def new_csrf_token(self):
        token = '0123456789012345678901234567890123456789'
        token = text_('0123456789012345678901234567890123456789')
        self['_csrft_'] = token
        return token
pyramid/tests/test_session.py
@@ -695,6 +695,13 @@
        result = self._callFUT(request, 'csrf_token', raises=False)
        self.assertEqual(result, False)
    def test_token_differing_types(self):
        from pyramid.compat import text_
        request = testing.DummyRequest()
        request.session['_csrft_'] = text_('foo')
        request.params['csrf_token'] = b'foo'
        self.assertEqual(self._callFUT(request, token='csrf_token'), True)
class DummySerializer(object):
    def dumps(self, value):
        return base64.b64encode(json.dumps(value).encode('utf-8'))