There are a number of different levels of security that a web site can offer when it comes to passwords. The particular hashing algorithm used can affect how easily someone who gains access to the hashed passwords can obtain plain text versions that will work with those hashes. Regardless of the hashing used though, having a hash applied to the stored copy of the password will mean that the site will be unable to tell you what your password is, it will only be able to offer you an opportunity to reset your password. If a site can tell you what your password is then your password is fully exposed and you should have serious concerns about using that site at all.
Where a site does hash passwords, a mechanism for resetting your password when you have forgotten it is required. Just how the reset works and how secure is what this article is about. All of the concerns with offering a password reset are related to trying to ensure that only the person the account belongs to can actually reset their password.
The first step in providing a password reset is having the person identify the account for which the reset is being requested. This by itself is insufficient though as if that were all that needed to be provided then anyone could reset the password on any account simply by identifying the account. We can apply the necessary second layer of security on the password reset by having the reset request send an email to the email address associated with the account rather than displaying the new password for anyone to see. This wouldn't prevent anyone from resetting any password at any time but it would hopefully limit access to the new password to the owner of the associated email account.
The next step is to try to limit the ability of people to request resets on other people's accounts. We can do this by asking for additional information about the account. As we have already decided that the reset will be handled via email, where the account isn't identified by the email address we could have them enter both the account identifier and the email address. We still only send to the email address already attached to the account but we ask for confirmation of what that address is before sending the reset email. Other information could also be requested and be required to match before allowing the reset. It all depends on how much you want people to correctly input before allowing the reset to proceed.
Anyone knowing all of the requested information will be able to request a password reset. Using an email to the associated email address as the next step helps ensure that only someone with access to that email address will be able to access the account after the reset. If we send the new password in the email then anyone knowing the information to trigger the reset will be able to change the password, they just will not know what it is changed to unless they also have access to the email account. The potential would exist for someone to be constantly resetting someone else's password. This would be annoying for the person who is constantly receiving emails with new passwords for their account. It would also mean that if the email account is compromised while a password reset email is still there that the person will have access to multiple systems.
The next step in this process to prevent people changing other people's passwords if they know all of the information to initiate a password reset is to send a link with a token in the email instead of a new password. The person receiving the email is then required to visit that link using the token in order for their password to be reset. Now if someone else requests the password reset the password will not be changed if the owner of the account ignores the reset email and doesn't click on the link. By also setting the token to expire after a set amount of time and allowing once only use we can also reduce the chances for the password being accidentally reset. This would not prevent someone who has compromised the email account from being able to request a new reset in order to obtain a link that hasn't expired but it does add an extra step or two to what they'd need to do.
A brute force attack on the database would be possible by trying every possible value for the token. With enough processing power and a short enough token someone could obtain the passwords from any current reset requests. The expiry time partly resolves this as they will only be able to test so many values before the token expires (if the owner doesn't use it first) and with a long enough token the portion of possible tokens that will be able to be tested will be negligible. Still they might get lucky and so including a non-random but not obvious section in the token can ensure that even when the would be password thief gets lucky and finds a valid token in the database that they will will be unlikely to get in. This non-random value can be regenerated from the record that matches the token and compared to the value attached to the token in the link. If the value matches then the password is reset but if it contains any other value at all then the reset token is expired. In the extremely rare event that they get lucky in guessing the token the owner would need to request another reset and the thief would not even realise that they had actually found a matching token.
If still further security is required then the web page the link takes them to could be changed so that it doesn't update the password straight away but instead asks additional questions to further confirm that the person who accessed the link is in fact the owner of the account.
This article written by Stephen Chapman, Felgall Pty Ltd.