Dear GlobaLeaks bug bounty team,
GlobaLeaks is vulnerable to timing attacks, because the
check_password() function performs a byte-by-byte comparison, which terminates early when two characters do not match.
Timing attacks are a type of side channel attack where one can discover valuable information by recording the time it takes for a cryptographic algorithm to execute.
~~~ def check_password(guessed_password, salt, password_hash): return hash_password(guessed_password, salt) == password_hash ~~~
== operation does a byte-by-byte comparison of two values and as soon as the two differentiate it terminates. This means the longer it takes until the operation returns, the more correct characters the attacker has guessed.
Link to source code: https://github.com/globaleaks/GlobaLeaks/blob/master/backend/globaleaks/security.py#L327-L328
~~~ hmac.compare_digest(hash_password(guessed_password, salt), password_hash) ~~~
compare_digest() function does not terminate as soon as two bytes are not the same.
On top of that, many password hashing modules come with a ready made time independent comparison function. The
bcrypt package uses the
~~~ import bcrypt
def bcrypt_password(): password = b"hunter2" hashed = bcrypt.hashpw(password, bcrypt.gensalt()) if bcrypt.checkpw(password, hashed): print("It matches! :)") else: print("It does not match :(") ~~~
In your case you are using the
scrypt module so maybe you want follow the recommendations from the docs:
~~~ import scrypt
def verify_password(hashed_password, guessed_password, maxtime=0.5): try: scrypt.decrypt(hashed_password, guessed_password, maxtime) return True except scrypt.error: return False ~~~
Link to docs: https://pypi.python.org/pypi/scrypt/0.8.0
Yours sincerely, Ed