25

I am currently working on a password reset flow. We have decided to go with a password reset link being emailed to the user's registered email and allowing them to follow that and input a new password of their choosing.

The current implementation we have in mind provides a one-time use token but not a timeout feature. Currently the research I have done on the matter seems to suggest that expiring these tokens is in some way more secure than not. However, people have not been citing why that is the case.

Can someone provide a use case where that token (while still being a one-time use) not expiring would be harmful security wise?

Additional Details: I am well aware that sending a password reset link is not the most secure way to handle this problem. Ideally we would not want to obfuscate this security to the email provider. However, we have made the decision to go with a password reset link. We are only trying to determine whether we want that to expire or not. For more information on the matter:

http://www.fishnetsecurity.com/sites/default/files/media/10WP0003_BestPractices_SecureForgotPassword%5B1%5D_0.pdf

Austin DeVinney
  • 351
  • 1
  • 3
  • 4
  • 1
    Related: http://security.stackexchange.com/questions/1918/can-anyone-provide-references-for-implementing-web-application-self-password-res – Null Nov 20 '12 at 18:03
  • 1
    1) Hash the reset token when storing it in the database. 2) Add an expiration date so that a 5 year old one still in someone's mailbox isn't still valid. – ewanm89 Nov 20 '12 at 19:38
  • Just wanted to follow up on the matter with my decision (in the comments): http://www.reddit.com/r/PHP/comments/13ioz1/password_reset_links_timeouts/ – Austin DeVinney Nov 20 '12 at 19:42
  • What reason do you have for not expiring the token outside of not wanting to bothering to implement it? What use case is there for a week old, month old or even years old reset link to work? It should be relatively quick and straight forward so add a short, 30 minutes to an hour time out on the link and let people know about it. – Evan Steinbrenner Nov 02 '16 at 20:33
  • I would say it depends on whether, once authenticated, a user can change their email address. If so, then you should definitely expire the tokens. But you forgot to tell us if this is the case. – symcbean Nov 29 '17 at 21:04
  • Over time you'll have more and more live password reset links - not sure how many users you have but if it's a significant number then the likelihood of one being discovered/brute forced continuously increases if they don't expire. – Arlix Nov 30 '17 at 10:06

8 Answers8

14

For example: if I remember my password, then don't reset it.

Now, if my email account is later compromised (or if I visit the link and anyone decides to peruse my browsing history), they can change my password at will and there is no way I can prevent it except to change my own password.

Unless, of course, you meant the token is only good for one page visit. That's certainly secure, but also inconvenient if I close the page, my session expires, etc.

Jon Newmuis
  • 897
  • 5
  • 6
  • 14
    Right. But this is not a valid use case in my eyes because if the email is compromised, then the attacker can already just navigate to myapp.com and request a password reset anyways. In other words, it's no more secure than a non-expiring link. – Austin DeVinney Nov 20 '12 at 18:09
  • (a) That sort of depends on your exact login flow; if your users log in using a username (rather than an email address), they would still be protected in this case, as long as you don't also include the username in the 'request password' email. (b) Regardless, the latter case still applies, and would certainly suck if I was using a public computer (sure, that's kind of the user's fault, but your job is to protect them). – Jon Newmuis Nov 20 '12 at 18:11
  • 6
    @AustinDeVinney Solid logic, but what if an attacker gains access to an email account that I used to use previously, and no longer have registered with your service? Or really in any case where the link goes to more than one of my inboxes (forwarding, for example). In such cases, requesting a password reset wouldn't work, but the link would still be a vulnerability. – SpellingD Nov 20 '12 at 20:52
  • 1
    If email service is compromised, every account linked to that email could be at risk trough password reset feature. Why should we even bother? – knagode May 13 '15 at 09:34
  • It is certainly your decision whether or not the risk is worth the effort of preventing, but it is still a risk. In my opinion, either the user should be able to invalidate the token, the token should expire, or both. – Jon Newmuis May 15 '15 at 04:11
  • @AustinDeVinney Not if the attacker only has access to the email, not ongoing access to the user's email account. For example, an attacker could find the old email on the user's hard drive or phone years later and use it to reset their password. Or the email could be backed up somewhere and an attacker could steal the backup. Or a data breach could occur at the user's email provider and the attacker could steal all their old emails. There many, many ways someone could get one-time access to a user's old emails without having ongoing access to their account. – Ajedi32 Nov 29 '17 at 17:41
12

On top of the scenarios that have been mentioned in other answers, the main reason I could see for having expiring password reset links is that the link could get cached or stored in a variety of locations and that could (under certain circumstances) allow someone else to get access to the users account.

  • Browser History. This one seems most likely as a risk. User resets a password from a shared PC, I'd expect the link to enter the browser history, so anyone who can get access to that browser can reset the users password and take control of the account.
  • Cached by a proxy server. Obviously if you've got HTTPS then most proxies won't see the link however in many corporates, SSL interception is used so those proxies will cache the link and also IIRC some mobile operators do this kind of thing in the name of cost saving.
  • Added to favourites. User follows link, thinks "this is handy" adds it to favourites, now anyone who uses that browser has access to their account. Not particularly likely but possible.

Whether these scenarios matter to you will depend on your use cases and the level of security that you're looking to provide.

Rory McCune
  • 60,923
  • 14
  • 136
  • 217
6

That's correct. Expiring these tokens is far more secure since an attacker with access to your database will be able to get these tokens and use them to reset users requesting a password reset but not completing their request.

I should also mention: Treat password reset tokens as big a secret as passwords. That is, you don't store them in plain-text, you generate them, send them to the user, and store it hashed in your database. That also prevents attackers with read access to just read and abuse the tokens.

Madara's Ghost
  • 349
  • 1
  • 10
  • 2
    "an attacker with access to your database" I feel like there are greater risks here and this goes far beyond tokens expiring or not expiring. – Austin DeVinney Nov 20 '12 at 18:06
  • 4
    @AustinDeVinney Not necessarily: if the attacker only has read access, they would greatly benefit from having a bunch of password reset tokens. – Null Nov 20 '12 at 18:09
  • 2
    if the attacker has read access he can read the username/email address, use the forgotten password feature and then read the token... – rook Nov 20 '12 at 18:10
  • 3
    @Austin DeVinney sql injection is very common, applications should defend against this attack as much as possible. This is why we hash passwords. – rook Nov 20 '12 at 18:11
  • @Rook Although in that case a token that doesn't expire would be vulnerable to the same attack. I think the OP's question is centered around a token that expires in a certain amount of time versus one that never expires. – Null Nov 20 '12 at 18:12
  • @Null Often programmers implement vulnerabilities without even thinking to ask if its horribly insecure. – rook Nov 20 '12 at 18:15
  • 2
    You should salt and hash the reset link while it's stored in the database anyway, treat it as a temporary password that way. Anything that acts as a password should be treated like one in your storage. – ewanm89 Nov 20 '12 at 19:36
6

OWASP has a great cheat sheet for password reset, their argument on the limited validity period is like @Jonathan Newmuis said that :

[...] if the user doesn't get around to checking their email and their email account is later compromised, the random token used to reset the password would no longer be valid if the user never reset their password and the "reset password" token was discovered by an attacker. Of course, by all means, once a user's password has been reset, the randomly-generated token should no longer be valid.

Ogre Psalm33
  • 195
  • 1
  • 2
  • 9
null
  • 1,193
  • 6
  • 16
  • 1
    I'm familiar with this cheat sheet. It came up in my research. However, the use case of a compromised email is not a valid use case for this. I detail my explanation in a reddit comment. Follow the link in the original post comments if you are curious. – Austin DeVinney Nov 20 '12 at 19:59
  • 2
    @AustinDeVinney, I think it is more effective and helpful when questions here are as self-contained as possible. If you feel this argument is not valid, I encourage you to revise the question to spell out why you believe that. Expecting people to dive into some external reddit link is not realistic. – D.W. Nov 21 '12 at 00:19
5

Point taken about how a compromise of the email account that is receiving the token negates some of the benefit of expiring the token. I do still think token expiry has some value, per Jonathan Newmuis.

Scenario:

  1. I request a reset for my account at ACME, which is emailed to my mailbox at Big Kahuna Corp.
  2. I remember my ACME password, and don't use the reset token.
  3. Sometime later, I switch to Gmail, but leave my Big Kahuna account lying around.
  4. Sometime after that, my Big Kahuna mailbox is compromised.

Scenario A: No Expiry

5b. The attacker finds the ACME reset token and uses it to compromise my ACME account.

Secnario B: Expiry after N days

5b. The attacker finds the ACME reset token which has expired, but he now knows I have an ACME account. He re-issues the ACME reset token - and since I have changed to Gmail (and changed my reset address accordingly on the ACME website), the reset token goes to Gmail, preventing a breach and indicating to me that I am under attack.

Yes, the example is contrived, but completely plausible.

Perhaps a good middle ground is to have a list of "currently valid" reset tokens that the user is shown on login, and given the opportunity to revoke them.

scuzzy-delta
  • 9,303
  • 3
  • 33
  • 54
4

The biggest problem is that you don't want to store the password reset token in the database in clear text. This produces a shortcut, where by the attacker doesn't have to crack the password hash, he can just reset the password. Storing a hash of the password reset token is a good solution to this problem.

It is a good idea that the password reset token expires and that its onetime use only. However, this is not as a big of a concern as storing these tokens in plain text. The biggest reason to have the token expire is to make it more difficult for the attacker to guess this value. If the attacker has access to the user's email then he can just send another token, which is a moot point.

rook
  • 46,916
  • 10
  • 92
  • 181
  • Well with the non-expiring solution we wouldn't be storing these tokens in the database at all, but still maintaining the one-time use functionality. – Austin DeVinney Nov 20 '12 at 18:18
  • 1
    @AustinDeVinney you must store them somewhere, a file on the system is still a form of database. Also there is no guarantee that the user doesn't wipe session cookies (browser set to automatically on exit and user exits it before loading mail client?) or other session information so session specific memory is going to cause issues. – ewanm89 Nov 20 '12 at 19:41
  • That is not accurate. There are ways around that so you do absolutely no storage, but it comes with other security risks that I deemed too great to take. The details can be found in the reddit post I linked in the comments of the original post. – Austin DeVinney Nov 20 '12 at 19:57
  • What about forming a password-reset token which encapsulates the present time along with a hash of the encapsulated time, the account's "last login" time, and the account's hashed password? If resetting a password equal to itself would re-salt it, such a token would automatically expire in all the cases when it should, without having to use any extra storage. What risks would you see with such a procedure? If the token used a longer hash than the original password hash, it might be possible to use the token to conduct an off-line brute-force attack on the original password hash, but... – supercat Aug 25 '14 at 17:34
  • ...password *hashes* generally have a lot more entropy than passwords. *Slight adjustment: To reduce the harm from a database compromise, have the token's hash function also hash a system-wide secret random string which gets regenerated on some periodic basis.* It has to be possible for an entity which knows only what the password system knows to generate password-reset emails, so there's no way to prevent such mails from being forged by an attacker who possesses all such information. Are there any other dangers? – supercat Aug 25 '14 at 17:43
1

I can think of a few reasons to limit validity:

  1. Defense in Depth: You are providing a sensitive, valuable token -- since this token can be used to gain access to an account. You don't know exactly what the user is going to do with the link -- what their email provider does; what the web proxies do with visited links; if this is a group email account vs individual account etc. (Other responders have given various scenarios). Limit the validity of the token to limit potential damage.

  2. Enumeration attacks: If I can get a token to be generated (say, by click-jacking you into clicking the 'forgot password' button), then even if I can't access that token, I can try to enumerate it. By limiting the validity of the token, you limit the amount of time I have to guess correctly.

Manish
  • 189
  • 1
  • 3
0

The expiration offers some additional protection but as you point out in your comments an attacker who has access to the email account can simply request a new token. It doesn't matter if the legitimate user no longer access the email account (as mentioed by OWASP), the attacker does!

A much better approach is to ask the user for some additional information during the validate token phase, information which is never sent by email. For example "what is your mother's maiden name".

Alternatively you can ask the user for this information during the "request new password link" phase and then set a time limited cookie/session variable indicating that the info is correct. When the user clicks the link in the email you also check for this cookie. In some ways it's a little less secure because if the attacker has access to the browser (or the cookies) he can still reset the password if he's quick enough. However this strategy does have the advantage of preventing junk emails, as the user must verify himself before you even send the reset email.