changeset 5902:840ebd16ddd9

use a constant time str comparison function to prevent timing attacks
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 09 Dec 2012 23:20:50 +0100
parents b9450db6c129
children e55effb840da
files MoinMoin/security/textcha.py MoinMoin/user.py MoinMoin/wikiutil.py
diffstat 3 files changed, 11 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/security/textcha.py	Sat Dec 08 22:54:04 2012 +0100
+++ b/MoinMoin/security/textcha.py	Sun Dec 09 23:20:50 2012 +0100
@@ -28,6 +28,8 @@
 from MoinMoin import log
 logging = log.getLogger(__name__)
 
+from werkzeug.security import safe_str_cmp as safe_str_equal
+
 from MoinMoin import wikiutil
 from MoinMoin.support.python_compatibility import hmac_new
 
@@ -137,7 +139,7 @@
             if not timestamp or timestamp + self.expiry_time < time():
                 success = False
             try:
-                if self._compute_signature(self.question, timestamp) != signature:
+                if not safe_str_equal(self._compute_signature(self.question, timestamp), signature):
                     success = False
             except TypeError:
                 success = False
--- a/MoinMoin/user.py	Sat Dec 08 22:54:04 2012 +0100
+++ b/MoinMoin/user.py	Sun Dec 09 23:20:50 2012 +0100
@@ -28,6 +28,8 @@
 except ImportError:
     crypt = None
 
+from werkzeug.security import safe_str_cmp as safe_str_equal
+
 from MoinMoin.support.python_compatibility import hash_new, hmac_new
 
 from MoinMoin import config, caching, wikiutil, i18n, events
@@ -538,7 +540,7 @@
                     salt = d[:2]
                     enc = crypt.crypt(password.encode('utf-8'), salt.encode('ascii'))
 
-                if epwd == method + enc:
+                if safe_str_equal(epwd, method + enc):
                     data['enc_password'] = encodePassword(password) # upgrade to SSHA
                     return True, True
                 return False, False
@@ -548,7 +550,7 @@
             salt = data[20:]
             hash = hash_new('sha1', password.encode('utf-8'))
             hash.update(salt)
-            return hash.digest() == data[:20], False
+            return safe_str_equal(hash.digest(), data[:20]), False
 
         # No encoded password match, this must be wrong password
         return False, False
@@ -1025,7 +1027,7 @@
         # check hmac
         # key must be of type string
         h = hmac_new(str(self.recoverpass_key), str(stamp)).hexdigest()
-        if h != parts[1]:
+        if not safe_str_equal(h, parts[1]):
             return False
         self.recoverpass_key = ""
         self.enc_password = encodePassword(newpass)
--- a/MoinMoin/wikiutil.py	Sat Dec 08 22:54:04 2012 +0100
+++ b/MoinMoin/wikiutil.py	Sun Dec 09 23:20:50 2012 +0100
@@ -20,6 +20,8 @@
 from MoinMoin import log
 logging = log.getLogger(__name__)
 
+from werkzeug.security import safe_str_cmp as safe_str_equal
+
 from MoinMoin import config
 from MoinMoin.support.python_compatibility import rsplit
 from inspect import getargspec, isfunction, isclass, ismethod
@@ -2553,7 +2555,7 @@
     #       if the ticket was created within a session.
     ourticket = createTicket(request, timestamp_str)
     logging.debug("checkTicket: returning %r, got %r, expected %r" % (ticket == ourticket, ticket, ourticket))
-    return ticket == ourticket
+    return safe_str_equal(ticket, ourticket)
 
 
 def renderText(request, Parser, text):