[Zope-dev] Salt-weakness in zope.app.authentication passwordmanagers?
Dan Korostelev
nadako at gmail.com
Sat Jan 17 12:53:37 EST 2009
Yeah, that's definetely a mistake! The hash needs to be generated
using both salt and password.
Also, I saw a technique when you generate a hash using double hashing,
like this: sha(sha(password) + salt).hexdigest(). It looks even more
secure :)
BTW, to fix it, we need to remember about migration of already stored
hashes. I guess zope.app.generations will do the job.
2009/1/17 Uli Fouquet <uli at gnufix.de>:
> Hi there,
>
> while working on a password manager tool (commandline) for Grok I
> stumbled over the usage of salts in the password managers of
> `zope.app.authentication`.
>
> In short, they seem to generate (and store) a salt number but do not
> make any use of it when it comes to creating the hashes (SHA1, MD5,
> whatever). As a result, same passwords lead always to same hashes, only
> the leading salt number is different. This could be exploited by
> dictionary attacks.
>
> The zope.app.authentication implementation for SHA1-encoding looks
> roughly like this (other hash-encodings have the same problem, if this
> is a valid problem)::
>
> def encodePassword(password, salt=None):
> if salt is None:
> salt = "%08x" % randint(0, 0xffffffff)
> return salt + sha.new(password).hexdigest()
>
> It looks to me that this way `salt` is only an arbitrary string that
> gets stored in front of the real hash value. The hash value itself will
> not change with the salt.
>
> When I run the following code (`checkPassword` like in
> `zope.app.authentication.password`)::
>
> def checkPassword(storedPassword, password):
> salt = storedPassword[:-40]
> return storedPassword == encodePassword(password, salt)
>
> for i in range(0,3):
> enc = encodePassword('asd')
> print 'Encode "asd"', enc
> print 'Check: ', checkPassword(enc, 'asd')
>
> I get::
>
> Encode "asd" 81bde2dbf10e2821bbbea527ea02200352313bc059445190
> Check: True
> Encode "asd" c96cfabdf10e2821bbbea527ea02200352313bc059445190
> Check: True
> Encode "asd" bdba5b69f10e2821bbbea527ea02200352313bc059445190
> Check: True
>
> As you can see, only the first eight letters change. And they are
> cleartext part of the encoded password. Not a problem for an
> dictionary-attacker: if one of the hashes in his/her dictionary are
> equal to ``f10e2821bbbea527ea02200352313bc059445190``, then the password
> is cracked. Salts do not improve the security level here, I think.
>
> What I assume to be correct, would be to build the hash from the salt
> plus password (instead of only the password)::
>
> def encodePassword(password, salt=None):
> if salt is None:
> salt = "%08x" % randint(0, 0xffffffff)
> return salt + sha.new(salt + password).hexdigest()
>
> Using this modified function, I get::
>
> Encode "asd" 11ac348fe526cc38813fca0e5bd0a59ec3a16686bfa42502
> Check: True
> Encode "asd" 08de8fa19212d743867f8867adee55a9efbe566a8ec56731
> Check: True
> Encode "asd" d454b892224b0cf5b41767acfa80a3732b82c52fc2ee5e9f
> Check: True
>
> Now it is harder for an attacker. His dictionary has not only to provide
> the pure hashes for every entry in the dictionary, but also 16**8
> variants for _each_ of the entries. That's it, I think, what salt is
> used for.
>
> As I am not a computer scientist nor a mathematician, I am not sure,
> whether these are valid concerns. But I would like to know, what others
> think about this. Maybe you can correct me here.
>
> Best regards,
>
> --
> Uli
>
>
> _______________________________________________
> Zope-Dev maillist - Zope-Dev at zope.org
> http://mail.zope.org/mailman/listinfo/zope-dev
> ** No cross posts or HTML encoding! **
> (Related lists -
> http://mail.zope.org/mailman/listinfo/zope-announce
> http://mail.zope.org/mailman/listinfo/zope )
>
>
--
WBR, Dan Korostelev
More information about the Zope-Dev
mailing list