I'm using Python's crypt package to persist encrypted passwords in a MySQL databse for a Django website. I'm not sure if this is a bug, but here's the code I'm using:
To encrypt/persist the password:
user.password = crypt(request.POST['password'], netid)
user.save()
To check for a correct password on login:
if crypt(password, email) == user.password:
# Grant acccess to the user's profile, etc.
The problem is the following. If I encrypt a password with variable netid = test@example.com
and request.POST['password'] = 'ABC123abc'
, it works fine. However, when I try to login, if I use the password 'ABC123abc[trailing_chars]'
, where the trailing_chars can be any valid string, I am still able to log in. Why is this? It poses to be a large security hole as is.
First of all, you should not be using an email address as a salt (the second argument) for crypt. This is not secure. You MUST pick a good random salt.
For traditional crypt, the salt is a two-character string chosen from the set [a–zA–Z0–9./]
. This version of crypt accepts only 8 input characters and discards all following characters from the input after the 8th. That is what you're seeing here.
Modern crypt implementations also support other algorithms that are cryptographically much stronger than traditional crypt but they are not available on all platforms. The new algorithms also don't limit the input to 8 characters.
To use one of these better algorithms (if you are using a platform that supports them), you need to supply a salt that is in a special format. This is how the function recognizes that you would like to use an alternate algorithm.
For the extra algorithms supported by glibc (and therefore available on GNU/Linux), consult the "Glibc Notes" section of the crypt manpage.
By the way, when checking the password, you don't need to manually extract the salt. The encrypted password already starts with the salt, so just pass user.password
(not email
) as the second argument to crypt
. This works whether you are using the old algorithm or one of the new ones. The choice of algorithm and generation of a salt in the correct format need only be done when encrypting the password, not when verifying it.