What is the best "forgot my password" method? [duplicate] - security

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Forgot Password: what is the best method of implementing a forgot password function?
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:
send the user an email with a link to a unique, hidden URL that allows him to change his password (Gmail and Amazon)
send the user an email with a new, randomly generated password (Wordpress)
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) 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.

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:
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.
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.
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.

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.

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.

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.

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

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.

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.

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.

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.

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:
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 tell the user to check their inbox for the reminder email but only send it if someone is a member; and
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.

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.

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).

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.

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.

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:
User enters username and email address
Email sent with link containing url and guid param which has been stored in db with 48 hour expiry
User confirms password to be reset
New password is emailed to user
Login with new password displays message or redirects to change password page.

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.

Related

Best practices for passwords on registration?

I have a website which users register an account. On the registration field, the form fields are:
Name
Email
Confirm email
Username
But there is no password field. When they hit submit, they are emailed a password which is very complex, such as LHJVjhwnv%uu5 or RbWM9!jeDZUQb.
I have appealed to my developer to instead make it so that the users can set their own password on the registration form. To confirm that password on the form, and then be sent a confirmation link to their specified email. Then this way they can at least log in to their account and verify their email via confirmation link. Or if they didn't, every time they log into the site it could remind them to verify their email etc or else they can't do much on the site (example). This way even if they don't get the confirmation link, they can still update their account email to a different email and have it resent. At least at this stage, they can log into their account, instead of not at all.
The response I have received from the developer is as follows
"The problem with providing the password on registration is that
you'll have loads of fake accounts. So people that just register with
a non-existent email address. At least with the email validation
you're proving the user exists, to a certain extent. If they register with the wrong email, they can just re-register."
I'd like to ask you all if the current approach the developer has employed is acceptable?
If not, what are some good reasons I could use to convince the developer to change?"
I've tried to explain the following
Every day there are 9-10 people who register and then directly use the "password reset" form right after. This form involves them putting in their email address that they signed up with, and then it emails them a link to SET a new password. So if they are setting a new password anyway, why not just have them set it in the first place on the registration form? Why would there be 9-10 people every single day using the password reset field, directly after registration? I'm pretty sure its because they are seemingly struggling with these complex passwords (which I am not against) that are being emailed to them and are missing a key or character, or do not seem to be aware of copy/paste or something like that. If they could just set their own password the first time around, they wouldn't need to run to the password reset field right after because of their emailed password not working. I thought it was weird how everyday theres always password reset emails. Not for everyone, but a good 9-10 people a day ever since I started using Mandrillapp to track the outgoing emails. This is backed up by the next point.
Every day there are at least 2-3 people who fill out the contact form indicating that the password they received is not working. Could all be avoided if they just could set it on their own. There may be even more that just don't bother contacting.
Out of nearly 8000 accounts, 50% have never logged in. My strong suspicion is that the Registration email containing their password goes to their junk folder/spam folder. This is despite me having proper SPF, DKIM, etc setup. 2 months ago, I decided to start using Mandrill to send mail to ensure it goes to the inbox, but still there's at least 1-2 people/day that say that they did not get their email.. which perplexes me. If they could define their own password, they wouldn't have to worry about waiting for their password via email, or not getting it entirely. This just further highlights my initial concern.
Thank you for your time!
I assume you already have a working password-reset page in place, so you can use just the same code to do the registration:
Let the user register with his email.
Send a link with a token to the user, a hash of the token is stored in the database.
If the user clicks the link and if the token is valid, welcome him and let him enter his own password.
This is exactly what you already have for password resetting, your site becomes no more (un)secure because an attacker could as well use the password reset function.
Of course weak passwords are a problem, so rejecting weak passwords is a must. Again this is the same you would have to do on the password-reset page. For password-resets you wouldn't send plaintext passwords neither.
Unconfirmed accounts can be deleted after a certain period, it means the user didn't do anything with it. If necessary the user can register again. This only works if the user is not allowed to login before doing the confirmation, what supports the procedure above. Of course it depends on the website if this confirmation is that important though.
The main reason not to send passwords in a mail is security: Mail isn't a secure medium. If you put a password in there, then many people can see it - consider allowing people to use your service without any kind of password instead to understand what I mean.
The main drawback of allowing people to chose their own password is that 95% will use 123456 or password.
Most big sites use this approach to balance security, business needs and comfort:
Allow user to set their own password. Reject the most simple ones (there are libraries for this). Note: Complex password rules drive customers away.
Send a confirmation link via mail.
Don't allow login until the link has been clicked.
If they try to login anyway, tell them that they have to click the link first plus provide a "send confirmation link again" link in case the first mail was lost.
I have appealed to my developer to instead make it so that the users can set their own password on the registration form....
This opens you up to a plethora of weak password and reuse attacks. Reuse has been empirically studied and reported between 50% and 76%. Other academic studies have stated nearly all users (almost 100%) reuse passwords.
So assigning passwords helps with major practical problems. After you assign the password, then you are subject to the same attack, though because a user may reuse the assigned password on another site.
...
I'd like to ask you all if the current approach the developer has employed is acceptable?
Yes, its acceptable as long as the password meets security requirements. I even prefer it, especially when user selected passwords are not checked against bad password lists.
Bad password lists are important because we know attackers use them. There are literally millions of passwords on them because of all the past breaches (did I mention password reuse is a pandemic problem?). The lists are easy to find, and one researcher recently released his list of 6,000,000+. See How I Collect Passwords.
Aaron is correct about email and plain text. You can actually place another security control to limit the exposure. Namely, require that your mail server use SSL/TLS or fail the connection.
Or, generate the password and display it to the user on the screen. Instruct the user to print the password so they don't forget it. I even tell my users to write them down and keep them in their wallet or purse.
The primary threat is a network based attacker attempting to gain unauthorized access to the server through weak/wounded/bad passwords. So an out-of-band/out-of-channel email is not too great a concern. And a lost wallet or purse is not too great a concern. The concern is the network based attacker guessing passwords or using {username,passwords} tuples from breaches of other sites.
Every day there are 9-10 people who register and then directly use the "password reset" form right after. This form involves them putting in their email address that they signed up with, and then it emails them a link to SET a new password.
OK, that's a security defect since the user can circumvent the security control.
For what its worth, I regularly use a random password generator to generate passwords for accounts. I don't even bother writing them down. When I need to access the account, I simply go through the Lost Password process.
That's how low value these things are to me. Every damn site wants a user to manage an account and password. I'm tired of expending the energy to manage all the accounts, so I don't even waste the cycles on it.
The problem with providing the password on registration is that you'll have loads of fake accounts. So people that just register with a non-existent email address. At least with the email validation you're proving the user exists, to a certain extent. If they register with the wrong email, they can just re-register
OK, so this is a different problem. BOT registrations are usually mitigated with a CAPTCHA. I've never really studied what to use for Real Users/Fake Accounts.
What is the benefit of a fake account? It seems to me the user is trying to get half pregnant. They either have an account, or they don't have an account.
Out of nearly 8000 accounts, 50% have never logged in. My strong suspicion is that the Registration email containing their password goes to their junk folder/spam folder. This is despite me having proper SPF, DKIM, etc setup.
Well, that's a different problem (that you should confirm through testing). This speaks to displaying the password for the user and telling them print the page.
There's a lot more to the subject of password management. You should read Chapter 7 of Peter Gutmann's Engineering Security.
I have appealed to my developer...
Finally, you are the boss. Fire the developer or contractor if they are not following instructions or coding against requirements. I'd be damned before I begged someone who I was paying for services.
Programmers are a dime a dozen, and you can find plenty of them at places like Rent-A-Coder. The Indians and Pakistanis work for next to nothing (under $10 USD per day in some cases). I don't know how they can work for so little and survive...

Time limited, or one time use, password reset tokens?

Users forget passwords, and (nearly) all membership sites need a way to help users get back in.
I'd like to implement the common scenario:
User hits site, tries to log in, can't, and realizes they forgot password - crap!
User enters email address and clicks "forgot password"
User gets email with a password reset link
Here's how I'm planning to implement this (C#/ASP.NET MVC):
When the user enters email and hits "forgot password" button my site will generate a GUID, store it on the member's entity in the DB (member.ResetToken), and email them a link with that GUID in the url (the email sent will inform them they can use this link to one time only)
User clicks the link and my site looks up their account based on that member.ResetToken from the url. If their account is found show them a password reset form, and when they complete the reset it clears the member.ResetToken from their account.
Here's my question: keep it like this (in which they can reset their password with that link at any time, now or in the future) or add a timestamp to limit how long they have to reset their password?
From a UX perspective the ability to reset your password whenever you're ready is great, but I want to make sure I'm not overlooking some security issues this could raise.
Your scheme actually works, but there are some points that could be improved. But first to your original question about the time limit:
Let's ask the opposite question: Why should a token remain valid infinit?
There is no advantage, when the reset-link can be clicked two years later, either the user clicks the link in about an hour or he has probably forgotten about the link (and can request a new one if necessary). On the other hand, being able to read the e-mails doesn't necessarily mean, that an attacker must hack the e-mail account, there is for example the open e-mail client in the office, a lost mobile phone, a backup on the (lost) USB drive...
The most important improvement is, that you should only store a hash of the token in your database. Somebody with access to the database (SQL-injection), could otherwise demand a password reset for any e-mail address he likes, and because he can see the new token, he could use it to set his own password.
Then i would store those reset informations in a separate table. There you can store the userid, the hashed token, an expiry date and the information whether the link was already used. The user is not in a special state then.
Maybe i misunderstood this point, but the reset link should point to a special page for password resets. When the user goes to the login page, there should be no special handling, the login page should not be aware that there is a pending password-reset.
The reset token should be unpredictable, this can be achieved best with a really random code, reading from the random source of the operating system.
So, there are a few problems with this approach that I was trying to elude to in my comment. When you store the "confirmation token" in the users password, you have just basically destroyed their password.
I, a malicious person, can then take a big giant list of email addresses and a bot net and flood your server with password reset requests and lock out your users from their account. Sure, your users will get an email for the reset, but if I can reset passwords fast enough, there may be a backlog of emails (or, if you do it synchronously, i can likely DoS the entire application).
I, a normal user of your system, may attempt to reset my password, and can't figure out why I'm not getting the reset email because I don't even know about a spam folder (or it never arrived). Fortunately, I just remembered what the password was, but it doesn't work anymore since the password is now an opaque GUID, and I'm basically dead in the water until I can find the reset email.
Here's the process you should use.
Generate a password reset request which you look up using a GUID, and you could likely also secure this by hashing that value with some private data and passing that in the URL as well to avoid a rapid attack. You can also lock this request down by making it only valid for a certain amount of time.
Once someone follows that link with a valid token and any other parameters you specify, they can then change the password, at which point you can now safely change the users password.
Flag the password request as having been completed, or delete it. You could also track information like IP address or something similar if you are really concerned about who changed the password if you are really concerned about it.
Send the user an email confirming that they have changed their password.
Also, just in case this isn't happening already, make sure you are hashing and salting the users password. It doesn't sound like you were doing that when you were just replacing the password with a GUID, so just double checking.
Users also forget to reset passwords (things happen). Being paranoid about passwords, I'd suggest limiting the link lifetime to 24 hours. This should be more than enough. It doesn't solve the problem of malicious intercept but it is better than nothing.
I would make the following suggestions:
Require some piece of information before the user is allowed to click the forgot password button. For example, require an email address and date of birth.
Ideally your user interface should not provide any feedback that allows a hacker to determine if his reset request succeeded. You don't want them farming your page for email addresses or DOBs. However this is a usability tradeoff, so whether you do this depends on how much security you really need.
You might also considering requiring a captcha which makes brute force and application DoS attacks much more difficult.
Expire the one-time token as quickly as possible. A couple hours is enough in my opinion. You should never consider email to be private-- it isn't, unless you are using a secure email technology (e.g. PGP) on top of the base protocol (most people do not). The last thing you want is for a black market to open up where your GUIDs are bought and sold, which is exactly what could happen if they have infinite lifespan.
Do not use GUIDs. They are not cryptographically random and are guessable. I suggest you use a cryptographic random number generator and translate it into base64.

Review my design: Password resetting facility for web site

When someone has lost a password, they click on the lost or forgotten password link.
They will need to enter their email address, then answer their own secret question
if the secret question is correct, an email will be sent to them with a link that expires after 24hrs.
As the email is sent, a record is entered in a database table holding this information:
- the email of the person who needs to reset the password
- the hour which the resetting of the password will expire
- the hour which the request to rest the password was submitted.
The sent link will lead the user to a form that allows them to enter their new password.
In this form they will need to enter their email address and their password X2.
When they click on submit, a check is made against db to ensure that the email is valid (one that the password is being reset) and has not yet expired (by comparing the two dates to see if the expiry time has passed, which is 24 hrs)
If the email is valid, and has not yet expired, and the two passwords match & meet the minimum req, then the new password is applied.
A confirmation message is given on success.
Q1. Is this a good model for password recovery?
Q2. How can I make sure that the link that is sent to the user's address is unique? In that no one will get the same link? So that nobody could just go to the password reset page and try different emails, rather have each account that needs to be reset have their own unique URL that work for that account only.
Regarding Q2:
I was thinking that when the user requests to have their password reset, a random unique id is generated and stored in the same record that expires after 24hrs. This random unique id's column could be called "rid"
The link in the email that will be sent to the user will end with ?rid=xxxxxxxxxxxxx
When the user clicks on submit in the page that resets the password, the "rid" at the top of the page is used to get the corresponding email address from the db, to compare it with the email address in the form. Doing this can ensure that each password reset case will have its own unique URL that no other account can use to reset its password.
Is this a viable solution?
Any contributions or suggestions will be appreciated.
Optimally:
Log me in through OpenID. Less coding complexity, less clicking, less typing, less time wasted.
Done. Question is moot. No need to worry any more, someone else already solved this problem.
There are a billion sites implementing a billion authentication schemes and in 99.999% of the cases it's unnecessary. Why should I as a user trust you as a developer to not store my password in plain-text or leak it or get hacked yourself? Few people use different passwords for every site...
If that's not possible, then make is as hassle-free as possible:
I click a "forgot password?" link. This automatically sends a mail if I've entered an e-mail already (e.g. after a failed log-in attempt). If I haven't entered one, simply hide the password field and tell me to do so. Don't reload or forward me to a different page.
I get a link to with some key (for example https://site.com/account/reset?key=a890ea8219175f890b7c123ee74a22). Some unique hash that is tied to my account and expires in so and so many hours. Use SSL if at all possible.
I click the link and you fetch my account details by the key, making sure it is valid and hasn't expired. I type in my new password twice. I already know what my e-mail address is, and you already know what my e-mail address is, and any would-be hacker would also know what my e-mail was, so don't ask me to type it in. Having the link last a whole day is overkill. Time it out in an hour or less.
I hate the security question. Don't ask me that. It's basically just a second password that's deliberately made less secure so you'll always remember it. I don't have frequent flier miles, I don't know my mother's maiden name, etc. Stop it. I know it's there to keep out strangers who might have hacked your e-mail, but unless you're PayPal I think it's just over-engineering.
When you have confirmed that the passwords match and they are acceptable, update the database (store only a salted hash of my password, not the password itself!) and log me in immediately. Do not redirect me to the log-in page where I have to retype information I've already given you several times now (and even though you already know it's me and trust me enough to change my own password). That is so annoying. Users are impatient.
I also dislike randomly generated passwords based on the following:
Usually I just copy-paste the password from the mail anyway. Copy-pasting a password is something you never want the user to do.
I have to go change the password manually, which means messing around in the user control panel or account settings or whatever. I am getting impatient! You could pup up with a "change your password" the minute I log in with a one-time password, but this means added code complexity. You now need to add a flag for this, add another redirect, handle the case where a user times out on entering a new password, etc.
Because I am only human, and humans have ADHD, I usually forget to do the above and I end up with a crap password I have to find and copy from my e-mail the next time I need to log in as well. My fault, but I'll still blame your site for it. ;-)
The randomly generated password solution is also implying the mentality that you'll always use a password-based solution, when link-based authentication seems to be the future (OpenID, etc.) in usability and security (I don't want a hundred small sites to know my login-details!).
Update to respond to comment:
Why the hash should be enough: if a hacker can guess the full 128+ bits (say) of your generated hash (and within an hour), then why wouldn't he or she also be able to guess the e-mail? I know that it "feels" a lot more secure to ask for the e-mail and/or a security question as well, but if you think about it, e-mails are usually very predictable and uniform, with low entropy rate. I doubt they can be counted on as containing more than 50 bits of information. (Probably a lot less.) I bet you I'd sooner guess your e-mail than I would a 50-bit random integer. But if it is a real worry, all you need to do is add more bits to the hash. 256 bits or so ought to do it for overkill mode -- SHA256(salt, email, old pw hash, time stamp, maybe some bytes from /dev/urandom) or similar... If a hacker can predict that, there's not much you can do really. Obviously he has control of The Matrix and could just project his mind onto the magnetic platters inside your hard drives if he wanted to.
Still Pro-OpenID: any new site I visit that demand I create a user ought to be very convincing as to why they want to know my (throwaway) password and what they offer me in security that OpenID or Google/Facebook/etc. does not -- or why they don't trust Google/Facebook/etc. Nobody (that I know) goes around remembering 30 different passwords. Usually people reuse them, so if these third party site creators wanted to, it'd be really easy for them to scam their users. If I registered at your site with my usual info, you could immediately take over my Last.FM and Reddit accounts if you wanted to, as well as probably a dozen sites I've used a couple of times and forgotten about. In fact, in these modern times, I kinda expect sites to either be ignorant or have malicious intent if they want details they strictly do not need, so that's why I call it a throwaway password -- with every sign-up it feels like I am saying "here, have my Reddit account, it's the same L/P as I'll be using for your site (otherwise I'd just forget). It's fine, I'm not particularly attached to it any way." Of course, Google could actually take over everything of my online self if they wanted to, but for now I'll trust Google more than you (no offense!).
First, I would suggest you treat a password-reset like a secure business transaction. SSL on, and a single request is independent of other requests for the same account. Generate a random, non-reusable transaction ID and associate it with THIS SINGLE REQUEST for a password-reset. Then, in the email you send to them, embed the transaction ID with the URL:
http://www.yoursite.com/passwordreset/?id=e3dXY81fr98c6v1
This so-called password-reset transaction should be associated with the account and have the metadata associated with a password-reset such as date of request and expiration date. The account itself should only know that there is/are pending password reset(s) associated with it.
Also, when a user asks to reset their password, forget the secret question - it's far more secure to send them an email that you should ALREADY have on file. (If you don't, then start collecting them!) - better yet, use their email address as their username.
When the user enters a new password from that transaction ID URL, you are trusting that it is the person you think it is. To ensure this, you can simply ask them to re-enter their username (which you already confirmed you are doing).
Q1. IMHO, there is a flaw. Why are you asking the user to enter a new password? I would rather generate a new random password and send it to him. After receiving it, the user can login using this randomly generated password, then change it in his/her profile.
I suggest the following system, used on the most websites:
The user enters a mail address in the "Password reset" form.
The mail is validated (ie. is there a user with this mail address in the database?)
The new password is randomly generated and sent by mail, then salted/hashed and saved to the database.
The user logins.
It's easy and common, so the users will not be lost.
Now, you can increase security (decrease abuse) by:
Setting password reset ratio. Once the form is submitted, the IP address and submitted data is remembered: now, for a few minutes, nobody from the same IP address will be able to reset a password anymore.
A newly generated password does not replace the old one: instead, both can be used. Imagine somebody resets a password of another user. This user must still be able to login with the old password, if he/she has not read or received the mail with the new password.
By the way, but it's just my personal opinion, do not provide secret question/answer feature, unless it is required. I have too much pain remember what I answered where, so I would probably have more risk to forget the answer than the password.

Why is challenge-response approach a poor solution for forgotten passwords?

My company is developing an online HR and Payroll application where securing access is critical. I'm clear on how to lock down most of the authentication/authorization processes, except for the 'Forgotten Password' page.
My initial plan was to require the user to enter both an e-mail address and a response to a previously selected/entered challenge question, with a temporary password being mailed to the e-mail listed (assuming the e-mail is valid). But I've read here and here (both on SO) that the challenge-response approach is insecure.
If we're only e-mailing a temp password though, is it really that insecure? The only more secure option I can think of would be to require the user to call their Customer Service Rep, which would greatly burden our employees.
What am I missing ... is there a better approach? Thanks!
Don't email a temp password, email the user a URL+token to a reset-password page. That way no password is ever changing hands unencrypted. It's also immediately obvious to the end-user that their account has been compromised if they try to go to that page and the reset token has already been used.
Added from the comments:
I think challenge-response ("secret question") aspects actually make things less secure, because they are generally things that can be discovered by researching public info about the target. The fewer steps total, the fewer that can be broken without anyone knowing. Letting reset emails go early and often is a good way to let a human know the attempt is being made.
As explained in this article, Governor Palin e-mail account was recently hacked using answers to previously asked questions. From the article:
As detailed in the postings, the Palin hack didn't require any real skill. Instead, the hacker simply reset Palin's password using her birthdate, ZIP code and information about where she met her spouse -- the security question on her Yahoo account, which was answered (Wasilla High) by a simple Google search.
There are a few common ways to manage lost passwords:
The Secret Question: It is actually a weaker form of authentication, just like people above posted. User may choose something really simple and it is easy to guess. I advise against this, because it does not require any technical "hacking"
Mail a new password. To circumvent this control, access to the e-mail account is required or a Man-In-The-Middle (MITM) position is required: You either read the temporary password from user's inbox or intercept in the middle. This approach is ripe for misuse, because anybody can reset the password and force the user out of the system, if he can't read the e-mail with new password.
Mail a password reset hash, to circumvent this, you need access to inbox or MITM, just like in case before this, but no passwords are actually reset until confirmation is done. Thus, user can not be locked out of the system, even if he did not read the e-mail. Add a cooldown timer to one reset per 8 hours to prevent Your system from flooding user's inbox.
Consider some out of band communication, for example, in the printed contract, write down a PIN. Then have the user call Your helpdesk from a known phone number (check with Caller ID) and give his username and PIN.
Wouldn't it be easy/feasible to outsource the whole password management just like SO did and use OpenId or similar? Of course this would add another dependency, but you'd trade that against the need to save (and secure) passwords and deal with them as you described.
You said it is an on-line HR and payroll application. Do you have the option of a user indicating he/she has forgotten his/her password and that generating a message to an HR representative or some official in the organization who can confirm identity and then issue a password reset?
In short, challenge questions are often the weakest link. They're easier to guess than a password and effectively operate as a proxy for a password, so they actually reduce security rather than enhance it by providing another attack vector that's actually easier to break. The Web Application Hacker's Handbook has some great information on this area.

What's a good alternative to security questions? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
From Wired magazine:
...the Palin hack didn't require any
real skill. Instead, the hacker simply
reset Palin's password using her
birthdate, ZIP code and information
about where she met her spouse -- the
security question on her Yahoo
account, which was answered (Wasilla
High) by a simple Google search.
We cannot trust such security questions to reset forgotten passwords.
How do you design a better system?
The insecurity of so-called "security questions" has been known for a long time. As Bruce Schneier puts it:
The result is the normal security protocol (passwords) falls back to a much less secure protocol (secret questions). And the security of the entire system suffers.
What can one do? My usual technique is to type a completely random answer -- I madly slap at my keyboard for a few seconds -- and then forget about it. This ensures that some attacker can't bypass my password and try to guess the answer to my secret question, but is pretty unpleasant if I forget my password. The one time this happened to me, I had to call the company to get my password and question reset. (Honestly, I don't remember how I authenticated myself to the customer service rep at the other end of the phone line.)
I think the better technique is to just send an e-mail with a link they can use to generate a new random password to the e-mail account the user originally used to register. If they didn't request a new password, they can just ignore it and keep using their old one. As others have pointed out, this wouldn't necessarily have helped Yahoo, since they were running an e-mail service, but for most other services e-mail is a decent authentication measure (in effect, you foist the authentication problem off on the user's e-mail provider).
Of course, you could just use OpenID.
Out-of-band communication is the way to go.
For instance, sending a temporary password in SMS may be acceptable (depending on the system). I've seen this implemented often by telecoms, where SMS is cheap/free/part of business, and the user's cellphone number is pre-registered...
Banks often require a phone call to/from a specific number, but I personally am not too crazy about that....
And of course, depending on the system, forcing the user to come in to the branch office to personally identify themselves can also work (just royally annoy the user).
Bottom line, DON'T create a weaker channel to bypass the strong password requirements.
Having seen a lot of posters suggest email, all I can suggest is DONT use email as your line of defense.
Compromising somebodys email account can be relatively easy. Many web based email services DONT provide any real security either, and even if they offer SSL, its often not default and you are still relying on the weakness of the email password to protect the user ( Which, in turn has a reset mechanism most the time ).
Email is one of the most insecure technologies, and there are good reasons why its a really bad idea to send information like credit card details over them. They're usually transmitted between servers in plaintext, and equally often, between server and desktop client equally unencrypted, and all it takes is a wire sniff to get the reset url and trigger it. ( Don't say I'm paranoid, because banks use SSL encryption for a good reason. How can you trust the 20-200 physical devices on the route have good intentions? )
Once you get the reset data, you can reset the password, and then change your(their) email address, and have permanent control of their account ( it happens all the time ).
And if they get your email account, all they have to do is have a browse through your inbox to find whom you're subscribed with, and then easily reset the password ON ALL OF THEM
So now, using the email based security, can lead to a propogative security weakness!. I'm sure thats beneficial!.
The question being asked Is one I figure is almost impossible to do with software alone. This is why we have 2-factor authentication with hardware dongles that respond to challenges with their own unique private key signature, and only if you lose that are you screwed, and you then have to deal with a human ( oh no ) to get a new one.
It 'depends' on the 'system'.
If you are a Bank or a credit card provider, you have already issued
some physical token to your customer that you can validate against and more.
If you are an ecommerce site, you ask for some recent transactions
-exact amounts, credit card number used et al..
If you are like Yahoo, an automated approach I would use is to send an
activation code via either a phone call or a text message to the cell
phone along with some other basic question and answers.
Jay
Do away with the (in)security questions completely. They're such an obvious security hole that I'm actually a bit surprised that it's taken this long for them to create a serious (well, highly-publicized) incident.
Until they disappear, I'm just going to keep on telling websites which use them that I went to "n4weu6vyeli4u5t" high school...
Have the user enter 3 questions and answers. When they request a reset present them with a drop down of 5 questions, one if which is a random one from the 3 they entered. Then send a confirmation email to actually reset the password.
Of course, nothing is going to be truly "hacker proof".
When users are involved (and mostly when not, too) there is no security; there is only the illusion of security. There's not a lot you can do about it. You could have 'less common' security questions but even they are prone to exploitation since some people put everything out in the public eye.
Secondary channels like email offer a reasonable solution to the problem. If the user requests a password reset you can email them a password reset token. Still not perfect, as others have said, but exploiting this would require the attacker to be somewhere in the line of sight between the website, its MTA and the users MUA. It's technically easy but I suggest that the reality is it's just too much work/risk for them to bother on anyone except very high profile individuals.
Requiring the user to supply SSL or GPG public keys at account creation time will help enormously, but clueless users won't know what those things are let-alone be able to keep their private keys secure and backed up so they don't lose them.
Asking the user to supply a second emergency password (kind of like PIN/PUK on mobile phone SIM cards) could help but it's likely the user would use the same password twice or forget the second password too.
Short answer, you're S.O.L unless you want to educate your users on security and then hit them with a cluestick until they realise that it is necessary to be secure and the slight amount of extra work is not simply there to be a pain in the arse.
Authenticating everything by sending emails is a reasonably effective solution. (although, that might not have been workable for Yahoo in this case :)).
Rather than messing about with security questions or other means to recover passwords, simply respond to password recover requests by sending an email to a predefined email account with an authorisation link. From there you can change passwords, or whatever you need to do (never SEND the password though - you should always store it as a salted hash anyway, always change it. Then if the email account has ben compromised, at least there's some indication to the user that their other services have been accessed)
The true answer is, there isn't a fool proof way to keep hackers out. I hate security questions, but if your going to use them, allow for user defined security questions. As a user, if I must have a security question on a site to set up an account, I really like having the ability to setup my own security question to allow me to ask something that only I know how to answer. It doesn't even have to be a real question in this case. But a users account is then as secure as the stupidity of the user, and the fact that many users will use something like "question?" and "answer!" or something equally dumb. You can't save users from their own stupidity.
Treating these security questions as something actually being two-factor authentication is totally misleading. From spurious items read before, when certain (banks) sites were required to have "two-factor authentication" they started implementing this as a cheap way to do it. Bruce Schneier talked about this a [while back][1].
Multiple factors are best things that are not-the-same. It should not be all things you "know" but something you know and something you have, etc. This is where the hardware authentication tokens, smart cards, and other such devices come into play.
[1]: http://www.schneier.com/blog/archives/2005/03/the_failure_of.html The Failure of Two-Factor Authentication
when its not an email system, email them a link to a secure page, with a hash that must come back in the query string to reset password.
Then if someone tried to reset your password, you would know, and they wouldn't be able to guess the hash potentially.
We use 2 guids multiplied together, represented as hex.
Well for one it should not directly reset the password but send an email with a link to reset the password. That way she would have got the email and known that it was not her who initiated the reset, and that her question / answer had been compromised.
In the case where the email address is no longer valid, it should wait for a timeout ( few days or a week ) before allowing a new email to be attached to an account.
Send a message to a different e-mail account, or text their cell phone, or call them, or send a snail-mail message. Anything that doesn't involve matters of public record or preferences that may change at any time.
Good security questions are a misnomer. They actually create a vulnerability into a system. We should call them in-secure questions. However, recognizing the risk and value they provide, "good" security questions should have 4 characteristics:
1. cannot be easily guessed or researched (safe),
2. doesn't change over time (stable),
3. is memorable,
4. is definitive or simple.
You can read more about this at http://www.goodsecurityquestions.com.
Here's a list of good, fair, and poor security questions.
IMO Secret questions should only be used as a very weak control with a time limit as part of a system.
Ex: Password reset system.
You are authenticated. Registrate your mobile phone number and your secret(not so secret) answer.
You forget your password.
You request to unlock it.
a) Your "Not so secret" question asks you for the "not so secret answer".
b) If correct, a text message is sent to the pre registrated phone.
This way, if your phone gets stolen and also, controls like pin/lock on the phone is not working. You still will have a measure of obfuscation for the attacker to get to reset the password until the time it is reported the phone is lost/stolen and can be disabled.
This usage is what i think the only purpose at all for the "not so secret" questions/answers.
So i would argue there is a place in this world for them and that usually a system needs to be the discussion.
Only provide questions that aren't on the public record.
always send the password reset to a registered email account (which is tricky for an email account) or send a PIN number to a registerd mobile phone, or a link to a IM address, etc - basically, capture some secondary contact information on registration and use it to send a 'password reset' link.
Never let anyone change their password directly, always make sure they go through an additional step.
I prefer to keep things simple and use an honor system approach. For example I'll present the user with something like,
Is this really you? Select: Yes or No.
How about requesting the users to enter their own security question and answer, and a secondary email (not the one where the password reset link is sent). Store the security question and answer hashed in the database for that extra step of security.
If the user forgets his/her password, send the password reset link to the user's primary email.
User then clicks on the link which redirects and asks for the security question and answer. If this step is successful then allow the user to reset his/her password. If the user forgets the security question/answer send a link to reset the security question/answer to the user's secondary email.
If the attacker gets access to one of the emails, it will still be useless without access to the other (very unlikely the attacker can get access to both). I know this process needs a lot of extra work on both the developers and users, but I think it is worth it. (Maybe we could give the users a recommended option to activate the security question/answer if they need this extra bit of security.)
Bottom line is that how strong or weak this system works will depends heavily on the user. The strength of the security question/answer and how well the two emails are "untied" (that is, there is no way of gaining access to one email through the other) will decide this systems strength.
I don't know if there are any problems with this way of doing it, but if any, I'd be happy if anyone could point those out :)
Generate a hash that contains the person's username and password and send it over Https to the user as a file. The user saves the file to disk. It is their responsibility to store this file in a secure location. Alternatively you can send it to their email address but this will result in less security. If the user forgets their login credentials they must then upload this file. Once the server verifies the username and password, they are then presented with a dialog to alter their password.
Due to the evolution of social media, security questions asked by websites are too easy to crack. Since most of the questions are personal information which is easily available on social media platforms one or another. One of the alternatives to avoid account hacking is to make password rules strict for login like adding special characters, numerical, capital letters etc. These kind of passwords are hard to decode and can enhance the security to a great extent.
But there are new alternative methods like multi-factor authentication, passwordless login, SMS authentication etc. SMS authentication is part of multi-factor authentication where a user is provided with an OTP on his/her cellphone which he/she need to enter in order to log in to a website. This is a secure way since the access of mobile is limited to the user only(mostly). Another multi-factor authentication method is sending a verification link to email to complete the signing in process. There is a very well written blog on this topic on Medium that explains this concept in a detailed manner.

Resources