views:

2008

answers:

17

I'm programming a community website.

I want to build a "forgot my password" feature.

Looking around at different sites, I've found they employ one of three options:

  1. send the user an email with a link to a unique, hidden URL that allows him to change his password (Gmail and Amazon)

  2. send the user an email with a new, randomly generated password (Wordpress)

  3. send the user his current password (www.teach12.com)

Option #3 seems the most convenient to the user but since I save passwords as an MD5 hash, I don't see how option #3 would be available to me since MD5 is irreversible. This also seems to be insecure option since it means that the website must be saving the password in clear text somewhere, and at the least the clear-text password is being sent over insecure e-mail to the user. Or am I missing something here?

So if I can't do option #1, option #2 seems to be the simplest to program since I just have to change the user's password and send it to him. Although this is somewhat insecure since you have to have a live password being communicated via insecure e-mail. However, this could also be misused by trouble-makers to pester users by typing in random e-mails and constantly changing passwords of various users.

Option #1 seems to be the most secure but requires a little extra programming to deal with a hidden URL that expires etc., but it seems to be what the big sites use.

What experience have you had using/programming these various options? Are there any options I've missed?

+4  A: 

There's no real difference between the security of option 1 or 2. Option 1 is effectively the same as preloading the new password in the form.

In fact, with the prevalence of phishing attacks, one could argue that encouraging use of option 1 with long URLs could make people less alert about clicking on long mysterious URLs.

Cade Roux
Option 1's URL is still public. There is no difference in security. SSL just secures the channel, it does not authenticate the user side, and only reliably signed certificates give any strength to the server side. In both Option 1 and 2, one would assume all password entry pages are SSL but most do not use any other kind of check like a special phrase. In all cases an email letting the user know their password has been changed is advisable, but if their email is already intercepted...
Cade Roux
-1 The emailed link is more secure, easier to use, and less likely to invite abuse. See my comments on Oli's post. Also stackoverflow.com/questions/613619/… has a great summary.
Cory House
Like Corey points out, I also think option 1 is more secure...
Ole Lynge
@Cory House, @Ole Lynge Option 1 and 2 have identical security. Everything needed to be known to compromise the account is in the email in both cases. They are completely equivalent from a security perspective and would even have implementation similarities such as expiring the link or the temporary password if it was not used.
Cade Roux
They only offer "identical security" if the temp password is stored in a separate field so the user can continue using their existing password (in case the forgotten password request wasn't submitted by them). And then, you have to hope the user isn't confused by the fact that at any given time their account can have 2 passwords, not one. And most users will think they need to use the new temp password when they receive a request they potentially didn't initiate, making this approach not only more confusing, but a bigger hassle for the user.
Cory House
+25  A: 

4) Crediting their bank account with two random amounts and ask them to enter those in.
5) Snail mail them some new password and ask them to enter it in.
6) Have them text or call some number and enter some value to a phone number with the mobile phone they registered on file.
7) Get out of the password management problem altogether by outsourcing it to OpenID providers like Stack Overflow, Facebook, blog engines, and others are starting to do.

Outside of those, use option #1 or #2 with the added feature that both expire in an hour.

Jeff Moser
I would decrease the validity period to just a few minutes, maybe 5–10 or so. That should be enough to check the e-mails and change the password.
Gumbo
I don't think it could fit to a community website, because we almost never use your credit card on this kind of website, and that could get bored the new user who is registering.But in some case, it could be useful.
Boris Guéry
Options 4 and 5 would, of course, make the most sense for sites where financial access is at stake, e.g. online banking, investments, etc. In particular, option 4 (and variants) are widely used to verify bank account details by services such as Paypal, etc.
Rob
While I agree expiration within a short timeframe is important, that's only intuitive and practical with a reset link. If you set a temporary password for forgot password requests, anyone who knows your username can change your password. And what happens when that password "expires" in x minutes? Thus, the link that expires is the right way to go.
Cory House
#7 is the winner. This reduces your liability too!
Dominik Weber
+4  A: 

Read the OWASP top ten to make sure your method is compliant.

Here is the direct link.

karim79
+2  A: 

I agree with your comments about option #3 being insecure.

As for programming either #1 or #2, option #2 is easier to program but #1 isn't much harder and both are probably about as secure as each other.

Whichever option you choose, you can also consider making it more secure by including requests for personal information (that you obtain during registration) as part of the forgotten password process.

I've programmed systems where you have a username and to get a new password you have to enter both your username and your email address. You can get sent a reminder of your username but the main point is that someone probably won't be able to guess your username and your email but if you do it just on email, there's less secure.

Secret questions are an approach to the personal information part. I personally think they don't offer a lot of value as people tend to choose questions that many people will either know the answer to, be able to guess or be able to find out. It is better than nothing however so long as you use it in conjunction with an already relatively secure method.

Obviously the more of this you do, the more programming work it is.

The simplest method is:

  1. Have a "remind me of my username" link (enter email). Don't tell the user if an email was sent or not because people can use that to find out if an email address is of a member. Always say an email was sent but only send it if someone is a member; and
  2. Require both username and email to get sent a new one-time password. That password should only last an hour or so. When the user uses it, they should be forced to change their password immediately.
cletus
He already wrote that in the question.
Martin Geisler
What do you do when you work for companies that insist they want cleartext passwords for customer support ?
PQW
If the company insists on cleartext passwords, there's not much you can do but advise them against it. I've been in that situation too. It's important to prevent "social attack" of such systems where someone impersonates a real user. So you should ensure you have adequate personal information on file to verify their identity and that any staff who can see the password are adequately trained in any verification procedure.
cletus
+7  A: 

Note that Option #2 also requires you to keep track of the old password and expire the new random password if it isn't used within, say 24 hours.

Otherwise I could annoy you by repeatedly issuing you a new random password -- if you are not near your email you might not know why you cannot log in with your normal password.

Also, please avoid requiring an "identification question". The answers to these questions are typically much easier to guess/lookup than real passwords -- so everybody can identify themselves as me. See the Sarah Palin story for a recent example of how insecure this is.

Martin Geisler
A: 

Either option 1 or 2 would be fine. As you said, option 3 is insecure as you would need to store the clear text password. You could probably get fancy and use a reversible encryption algorithm to store/retrieve the password, but with better alternatives available to you there's no reason to go down that road.

Justin Ethier
A: 

There is an additional option that you can use in combination with any of the options that you mention:

You can let the user write a reminder for their password, that you send to them as the first step when they have forgotten the password. If the reminder doesn't help the user, you can go on to the next option.

As the reminder isn't the password itself, it's safe to send by mail (or perhaps even display directly on the page).

Guffa
A reminder will reveal information about the password, e.g., "the name of my cat", "my first car brand", etc... for that reason I don't like them.
Martin Geisler
@Margin: It's of course up to the user to choose a reminder that noone else understands, just as it's up to the user to choose a password that isn't easily guessed.
Guffa
And a hacker can get to the 'next option' so what have you gained?
UpTheCreek
@Sosh: You mean compared to sending them directly to the "next option"? The user isn't awlays forced to go through the process of changing the password, or you don't have to send the password in a mail where it may be intercepted.
Guffa
A: 

If you are hashing them Option 3 is unavailable and if you are not hashing them, shame on you. :)

I prefer option 1, sending a reset password link sent to their email which allows them (for a limited time) to reset their password. It does require more work, but it's easy for them to use and ultimately as secure as their email login process.

Anthony Potts
+2  A: 

Option #1 is probably the best. #3 is insecure (and I also suggest using something stronger than MD5, such as SHA1). Option #2 is not good because it allows any random person to lock you out of your account until you check your email, unless you use a security question. And security questions are often easier to crack than passwords.

Zifre
+5  A: 

Options 1 and 2 as insecure as each other.

There. I said it. If the user's email account has been breached, there's no reasonable secure way to do things unless you collect more private data like their address, mother's maiden name - all of which can be guessed.

The best (albeit most annoying) version I have seen is where you need to remember a secret question and a secret answer. It means the user has to remember which question they asked, which, of course, can always be forgotten too!

If they forget the question and you're a "real" company, there's always the option of sending the user a token through the post, with instructions on how to reset all their security... It's very unlikely that a hacker will have access to their real life mail.

A skew on that would be to collect a telephone number when the user created the account. If that existed and they couldn't remember any of their details, you could set up some sort of automated calling system that told them how to reset their details.

And one thing to mention about #2: Don't let the process overwrite the current account password. If that happened anybody could say they forgot any account's password, triggering lots of unwanted password changes.

Oli
Interesting thoughts, it means that if you ever find out that your e-mail password has gotten out of your hands, you need to change all your passwords on all sites at which your account is linked to that e-mail address.
Edward Tanguay
Secret question and answer can work, but often don't (Google "forgot my secret question"). A recent study questioned how secure they are. http://www.itworld.com/security/68143/study-secret-questions-dont-safeguard-passwords
DOK
No, they're by no means perfect. The only real way to make secret questions is to keep them completely secret (ie have the user make the question) but that means there's something else for them to forget.
Oli
IMO the only *real* security comes when you link offline details with the account so people can be contacted via phone or mail. Relatively slow and expensive but much more secure.
Oli
@DOK: so, someone questioned the security of security questions? ;)
Erik Forbes
Or, like me, you could always use the same secret question, but supply an unrelated, easily remembered answer. For example: "What is your mother's maiden name?" "Spaz ate the Dopefish"
Toon Van Acker
-1 Option 1 _is_ more secure. The password reset link is only valid for a short period, so there's a very small window for an attacker to strike. And even if they did, the user would know because the reset link would no longer work if the attacker intercepted the link and used it to change the password. If the new assigned password isn't changed by the user immediately, the attacker who intercepted the password can quietly impersonate the user indefinitely. Also, #2 allows anyone to change your password if they know your login. Not good.
Cory House
@Cory House: You forgot a vector: The attacker has the email account details and *then* requests a password reset. If the attacker can prompt the reset procedure without any other "secret" data, 1 and 2 are equally insecure. As for ~"quietly impersonating" the user using #2's random password, I would argue most users change the random junk passwords as soon as they log back in.
Oli
@Oli - If the user's email account is compromised then neither 1 or 2 work. I didn't forget that vector - it's not relevant to this comparison. And while a user may indeed change their password, some won't unless all are forced. At which point you have to ask why you're forcing someone to key in a temporary password they're immediately going to change when a link would be equally secure and more convenient. Plus, if you set a temporary password the minute someone requests a pass reset anyone who knows your login can lock you out of your account.
Cory House
@Cory - I dealt with the lock-out issue in my answer and the most recent reply: you need more secret data.You need to challenge the user with a secret question and answer... My point is the only insecurities in good implementations of both 1 and 2 both rely on a compromised email account. *Your* argument against 2 is the password can be intercepted. Well so can the password link. They are equally insecure. To protect against email hacks, you need to take it offline and mail/phone them another token.
Oli
@Oli - Secret questions/answers actually make the site _less_ secure since they become yet another vector for attack, and often the weakest link. See http://stackoverflow.com/questions/613619/why-is-challenge-response-approach-a-poor-solution-for-forgotten-passwords for more info.
Cory House
@Cory - If I'd said *just* use secret data, I'd agree... But I didn't... Adding extra layers of secret data does add to security.
Oli
@Oli - The problem is secret data is typically used as a proxy for a password, which actually decreases security. Now if you're talking about requiring a user to answer additional questions before they can even get an email sent to them for a password reset, then you're solving a problem that doesn't need to be solved and introducing a new problem - the user can't reset their password if they've forgotten this additional data. If you simply send a link to reset a password, there's no need for these extra questions which actually _reduce_ security and usability.
Cory House
@Cory - Secret data (to stop either 1 or 2 sending emails) means an attacker needs that information about the user. They can't rely on a compromised email account. Yes it's a pain in the arse if you forget your mother's maiden name but I fail to see how this is less secure.
Oli
@Oli - So you're condoning a system where the only way you can reset the password you forgot is to remember some other piece of information? You're describing using challenge questions in a non-traditional way, and it would lock many users out of their account without recourse. Challenge questions are traditionally used to harden a login process, and I endorse that idea. But requiring the user to provide more easy to forget data just so they can retrieve their password is a fundamentally flawed approach and a band-aid fix that's not necessary if you simply send them a reset link instead.
Cory House
@Cory - Re "condoning": I'm just explaining that you're wrong when you say secret data is insecure - It's not. Re "using challenge questions in a non-traditional way": Get real. Challenge questions are there to challenge identity at *any* stage. Re "easy to forget" There's a good why these questions are usually big points about life, not "What did you eat on 2nd December 1993?". Re "fundamentally flawed": They're both flawed. They both rely on a secure email account and secure email transmission. Too many people in the real world use email over insecure networks without any encryption.
Oli
@Oli - I never said secret data is insecure. You're just condoning using it in a way that adds no value. If you simply send a user a reset link there's nothing to bother protecting.
Cory House
@Cory - Unless the email can be snooped which as I have already said, is trivial half the time. Take any major bank where you have online access. What happens if you forget your password or pin? Do they email it to you? No. You call up, give them your account info, answer secret questions and then they post you out a new PIN/password/whatever. It's good enough for banks but not you.
Oli
@Oli - We're not discussing the _"best"_ approach, we're comparing 3 approaches that are actually practical for an individual. This question isn't for a bank, it's a decision between 3 options listed and option 1 is preferable as I've clearly outlined.
Cory House
@Cory - My point was that secret question data makes the whole process a lot more secure. It makes all three approaches more secure (though you should never go the third route because you should never store the password in the first place). We've flipped and flopped through this so I'll concede #2 is annoying-to-the-point-of-uselessness without another layer but both are as *vulnerable* as each other. Asking, storing and prompting security question/answers is not beyond somebody writing an authentication script; and you don't have to challenge them offline, it's just even more secure that way.
Oli
A: 

You could made a mix between #1 and #2, taking advantages from both:

Send the user an email with a link to a unique, hidden URL that allows him to change a new randomly generated password.

That page could be SSL, and the password could expire in 12-24 hours.

eKek0
+1  A: 

Option 4: Require user to reset password by entering their account name AND email address. As long as you aren't disclosing real names or email addresses on the site (WHY would you in this day and age?) this is a reasonably secure and tamper-proof method. Send a link to a reset page, not the password itself.

Option 5: Use OpenID and pass the responsibility to a 3rd-party to worry about it.

Honestly though this is a lot more effort than most sites require. I for one LIKE receiving plaintext passwords by email because I store them in a "registrations" folder in my inbox. That way I can lookup passwords for sites when I forget them (which happens a lot!). If somebody is reading my email I have bigger problems to worry about than people using my twitter account (if I had one). Of course banks and corporations have stronger requirements but you didn't specify what your site is. That's the key to the best answer.

SpliFF
Yes, the site I am making is quite low-profile (100 members) and so am shooting for something that balances user convenience with programming/testing effort (it actually does take a lot of programming, testing to make sure that all security holes are close when you are sending out hash codes to temporary URLs and covering all the bases (user doesn't takes too long, enters wrong password when changing, etc.).
Edward Tanguay
+4  A: 

Just a quick note on something not specifically in regards to your question. You mentioned you used MD5 to hash stored passwords. Regardless of whether you choose to use Options 1 or 2 (3 is going to be the least secure as, for obvious reasons), MD5 is a cracked hashing algorithm, and can actually make it fairly easy for hackers to gain access to accounts protected by MD5 hashing.

You can read more about the vulnerability it at the following URL: en.wikipedia.org/wiki/MD5

A better hashing solution would be something like SHA, which is still a stable and secure hashing algorithm. Combined with option #1 or #2, you should have a reasonably secure system in place to protect your users passwords, barring all but the most determined hackers.

jrista
SHA-1 is currently being phased out by 2010: http://www.securityfocus.com/news/11292
Cade Roux
This has nothing to do with the question, does not mention the need for salt. Even if md5 was vulnerable to pre-image or second pre-image attacks, I fail to see how it would make this scenario any less secure. These hashes are not leaking out of the system (at least they should not) IF they are leaking out of the system even if SHA512 was used it could be brute forced unless a salt was used that was kept private.
Sam Saffron
Lol, brute force SHA512 in a short enough time frame for it to be worth while to the hacker? MD5 can be CIRCUMVENTED in a very short amount of time...were not talking brute force here...were talking about bypassing a security measure because of a fundamental flaw. Its a valid concern that I thought should be noted. And a hash doesn't need to leak out of a system...all you need to do is find an input that generates the same hash...and thats exactly what the MD5 vulnerability allows, in a reasonable enough time frame for it to be a concern. Salting can't even prevent it with MD5.
jrista
@Cade Reoux: I mentioned SHA in general, not specifically SHA-1. The .NET framework supports a wide variety of SHA variants.
jrista
+2  A: 

Option #1 has a couple of major advantages over #2. If a random user types in my email address into the "I have forgotten my password" box, then my password will not be reset. Also, it is slightly more secure in that there is no permanent record of the site's password stored in your gmail inbox forever.

A critical missing piece here is that the link you provide in #1 should only work for one password reset and have a time limit

All these solutions mean that you are treating your email inbox as the "one ring" that rules them all. Most online services seem to be doing this now days anyway.

My preferred approach is to go with openid where possible. Password management is hell that no one seems to get quite right. It's easier to hand this problem to someone else.

Sam Saffron
A: 

I've tried a couple of methods that I've not really been happy with. What I've settled on for the next project is to:

  1. User enters username and email address
  2. Email sent with link containing url and guid param which has been stored in db with 48 hour expiry
  3. User confirms password to be reset
  4. New password is emailed to user
  5. Login with new password displays message or redirects to change password page.
Duncan
+2  A: 

I'm shocked at the upvotes on answers describing #1 and #2 as equivalent. They aren't at all. Sending the user a short term link to change their password is the most convenient, most commonly used, and most secure approach that doesn't involve an out of band interaction (mail, text msg, etc.). A few reasons:

  1. Setting a temporary password via a forgot password link allows users to effectively change a user's password and lock a user out of their account if they know the user's login. With a link, the user simply knows someone is messing around and their access isn't impacted.
  2. The password reset link is only valid for a short period, so there's a very small window for an attacker to strike. And even if they did, the user would know because the reset link would no longer work if the attacker intercepted the link and used it to change the password. If the new assigned password isn't changed by the user immediately, the attacker who intercepted the password can quietly impersonate the user indefinitely. So the big difference is, while a hacker can intercept the reset password link email, if they use the link to change the user's password, the user will know something is wrong because the link won't work and they'll generate another password reset request.
  3. Easier to use - the user simply clicks a link in their email rather than typing a new random password you've generated.

And security questions often make a site less secure, not more - they're another attack vector and often the weakest link. I highly recommend reading The Web Application Hacker's Handbook for an excellent discussion on this topic.

Cory House
A: 

Instruct the user come personally to your offices and prove her identity with id card or passport.

This, of course, assumes that you have offices near your users and that the account are valuable enough to justify this procedure. Suitable for example banks.

Juha Syrjälä