سؤال

Is it possible to add a salt to passwords in .hpasswd files? I assume not since the server would need the salt for each user in order to verify the password and I can't think of how it would get them, but otherwise if the list was to be obtained it would be rather vulnerable. Is there a solution?

Many thanks for your help, Ben

هل كانت مفيدة؟

المحلول

By default htpasswd uses the standard crypt function and thus passwords are already salted - note in this example that both users have the same password yet the hashes are different:

simon@diablo:~$ htpasswd -b -c htpasswd simon abcd
Adding password for user simon
simon@diablo:~$ htpasswd -b htpasswd simon2 abcd
Adding password for user simon2
simon@diablo:~$ cat htpasswd 
simon:NWvm/LCCxQ64E
simon2:2I.LBzsRqULN6

(note: the -b flag is normally discouraged because other users can see your command line arguments and hence the password)

The first two characters of the hash are the salt; passwords are verified by calling crypt() again. Entering the wrong password produces a string that's unequal to the hashed password:

>>> from crypt import crypt
>>> crypt("wrongpass", "NWvm/LCCxQ64E")
'NWbxQgX1unvso'

whereas the correct password produces the expected hash:

>>> crypt("abcd", "NWvm/LCCxQ64E")
'NWvm/LCCxQ64E'

htpasswd -m uses a different algorithm that's MD5-based and uses a longer salt:

simon@diablo:~$ htpasswd -m -b -c htpasswd simon abcd
Adding password for user simon
simon@diablo:~$ cat htpasswd
simon:$apr1$mfvnBVmG$iIHIHOaH9vcImG5G.8eVa/

Here, the salt is the 8 characters between the second and third $.

htpasswd -s stores a SHA-1 digest with no salt; this appears to be for compatibility with Netscape/LDIF:

simon@diablo:~$ htpasswd -s -b -c htpasswd simon abcd
Adding password for user simon
simon@diablo:~$ htpasswd -s -b htpasswd simon2 abcd
Adding password for user simon2
simon@diablo:~$ cat htpasswd 
simon:{SHA}gf6L/odXbD7LIkJvjleEc4KRes8=
simon2:{SHA}gf6L/odXbD7LIkJvjleEc4KRes8=

These can easily be reversed - convert into a hex digest:

>>> "".join("%02x" % ord(c)
...      for c in "gf6L/odXbD7LIkJvjleEc4KRes8=".decode("base64"))
'81fe8bfe87576c3ecb22426f8e57847382917acf'

then use an online hash database.

نصائح أخرى

The htpasswd utility already does use salts in most cases:

The crypt() and MD5 formats permute the representation by prepending a random salt string, to make dictionary attacks against the passwords more difficult.

And that's (sort of) the purpose of salts in password files. While salts have to be included in the server's .htpasswd file for the server to be able to check passwords, it is the numerous different possibilities of what a salt could be that defends against such attack techniques as rainbow tables.

However, if your users pick weak or common passwords, password cracking is a problem anyways, since the attacker (presumed to have access to the password file) will try those first, very quickly in fact (not limited by the speed of the server and Internet connection), by guessing in the normal way. The best advice I can give is that users should always pick strong passwords.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top