diff options
| author | Chris McDonough <chrism@plope.com> | 2011-10-14 20:41:21 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-10-14 20:41:21 -0400 |
| commit | 5f0d6d54572a4c2182d730daf5f0a683cabb36ca (patch) | |
| tree | 65b2a5aeff45e274310acecdd76db926cf3cbaf0 | |
| parent | 5a20b131b921362785dda87409ca8eb3a1a9c6a1 (diff) | |
| parent | d1527f421d8ad6163304cbb3bcec3b2c2124c9dc (diff) | |
| download | pyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.tar.gz pyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.tar.bz2 pyramid-5f0d6d54572a4c2182d730daf5f0a683cabb36ca.zip | |
Merge branch 'master' of github.com:Pylons/pyramid
| -rw-r--r-- | pyramid/authentication.py | 6 | ||||
| -rw-r--r-- | pyramid/session.py | 12 | ||||
| -rw-r--r-- | pyramid/util.py | 20 |
3 files changed, 28 insertions, 10 deletions
diff --git a/pyramid/authentication.py b/pyramid/authentication.py index 955e870b4..3909ce2d8 100644 --- a/pyramid/authentication.py +++ b/pyramid/authentication.py @@ -22,6 +22,8 @@ from pyramid.interfaces import IDebugLogger from pyramid.security import Authenticated from pyramid.security import Everyone +from pyramid.util import strings_differ + VALID_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9+_-]*$") class CallbackAuthenticationPolicy(object): @@ -485,7 +487,9 @@ def parse_ticket(secret, ticket, ip): expected = calculate_digest(ip, timestamp, secret, userid, tokens, user_data) - if expected != digest: + # Avoid timing attacks (see + # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf) + if strings_differ(expected, digest): raise BadTicket('Digest signature is not correct', expected=(expected, digest)) diff --git a/pyramid/session.py b/pyramid/session.py index a59f9c628..8d0c6c423 100644 --- a/pyramid/session.py +++ b/pyramid/session.py @@ -13,6 +13,7 @@ from pyramid.compat import text_ from pyramid.compat import bytes_ from pyramid.compat import native_ from pyramid.interfaces import ISession +from pyramid.util import strings_differ def manage_accessed(wrapped): """ Decorator which causes a cookie to be set when a wrapped @@ -262,17 +263,10 @@ def signed_deserialize(serialized, secret, hmac=hmac): sig = hmac.new(bytes_(secret), pickled, sha1).hexdigest() - if len(sig) != len(input_sig): - raise ValueError('Wrong signature length') - # Avoid timing attacks (see # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf) - invalid_bits = 0 - for a, b in zip(sig, input_sig): - invalid_bits += a != b - - if invalid_bits: - raise ValueError('Invalid bits in signature') + if strings_differ(sig, input_sig): + raise ValueError('Invalid signature') return pickle.loads(pickled) diff --git a/pyramid/util.py b/pyramid/util.py index a43b50aef..3eb4b3fed 100644 --- a/pyramid/util.py +++ b/pyramid/util.py @@ -208,3 +208,23 @@ class WeakOrderedSet(object): oid = self._order[-1] return self._items[oid]() +def strings_differ(string1, string2): + """Check whether two strings differ while avoiding timing attacks. + + This function returns True if the given strings differ and False + if they are equal. It's careful not to leak information about *where* + they differ as a result of its running time, which can be very important + to avoid certain timing-related crypto attacks: + + http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf + + """ + if len(string1) != len(string2): + return True + + invalid_bits = 0 + for a, b in zip(string1, string2): + invalid_bits += a != b + + return invalid_bits != 0 + |
