Nitrooos

Developer's thoughts

Secure mechanism of password reset

nitrooos

Today I want to share few thoughts about implementing password reset mechanism with you, mainly because of popularity of such functionality on modern websites. That fact suggests the implementation shouldn’t be problematic, also from the security perspective. However, I don’t like relying on suggestions, so I’ll start with asking a question:

Is it possible to make such functionality secure?

The answer is, in my opinion, NO. Or, at least when you have in mind a traditional mechanism using e-mail service and addresses assigned to the users. And I don’t have in mind the fact that the absolute security is impossible. The SMTP (protocol of exchanging messages betwen e-mail servers) is by default uncrypted. It creates an impossible to exclude (a little one, but always) danger of capturing the correspondence between application’s server and its user by an unauthorized entity. Thus all the advices below will aim to reduce that risk.

Rule no. 1: Token based mechanism

By sending to the user only the token which allows for a password change and not e.g. a temporary password, we don’t change user’s state in our systems. The access to the user’s account is still possible only by the old password, we only know there was a try to change it. In the case of temporary password the user’s password has already been changed, what causes a serious security hole. Then every user can change a password of every other user, the only condition is that it knows a proper e-mail address. It won’t know the new password, but we don’t want to make such miracles possible in our application :) The third option, so sending current password via e-mail also is not acceptable, because as professionals you don’t store the passwords in plaintext (do you???) So the most sensible solution seems to be token based mechanism of password reset, sent inside a link to user’s e-mail address.

Needed properties of the token

Of course, when we decide on using a token, we have to ensure its concrete properties, I mean it has to be:

Ensuring all the properties above requires us a little effort, so one may ask: why each of them is actually needed?

Disposability is absolutely necessary, because such possibility as enabling password’s change should be closed immidiately after taking this action (more on this will be later in this post).

Unpredictability means using actually random number generators to create a token. This makes it impossible to just guess (or indepedently construct) a valid token by an unauthorized entity.

Proper length of token makes sure that a simple brute force attack won’t be possible. After all, generating a valid token in a short time by just trying all possible variants cannot be done. In practice, we should use at least 32-characters long tokens.

Assigning token to concrete, one user ensures, that token generated by user A can be used to change the password of user A, but not unaware user B.

Yet another important note about token’s content

Please don’t store in a generated token the information about user’s account nor its expiration date. Embedding such information inside token will make it possible (potentially) to reset password of a different user then whom the token was generated for. Modifications could also e.g. increase its validity. The rule of thumb is that token should be only used for an identification of proper row in database, I mean an assigned user.

Rule no. 2: Token invalidation as fast as possible

The obvious thing is since we have made it possible to change password in application, the prodecure should be easy, without leaving open “doors” to the system. A general rule says: leave the token valid only as long as absolutely necessary, but not longer than x time units. In practice it means:

In real world we can notice also some additional mechanism, e.g. blocking token after its first usage. In consequence, the user can go into a reset password page only once, all following requests will fail (however the token will remain valid).

Rule no. 3: New salt for new password

When user was authenticated by using a valid token, now is the time to actually change its password in a database. We have to keep in mind, that we should use new salt for hashing that new, changed password. The question is: why is it important? If the salt is shared between all the password in the database, then the case of 2 users with the same password will end up with 2 identical hashes stored in database. Unfortunately, such situation is impossible to exclude. What would it mean for an attacer in the case of data leakage? It would be a strong premise, that during the hash generation procedure the same salt was used.

Rule no. 4: Invalidation of all existing sessions

Successful finishing the password change process doesn’t end our efforts, because still there may be many existing sessions of an user authenticated by the old password. What does it matter? One of the causes of password change may be the situation when the old password was compromised. That’s why all existing sessions of the user changing its password need to be invalidated. After successful password change, the user should be redirected to login page. This behaviour ensures the only person able to log in into application is the user who changed password, only using the new one.

Summary

The rules above show you few ideas to make your password reset mechanism (relatively) secure. Of course, you can introduce another improvements. Nevertheless, these are the basic ones, which you should start from.

Sources: