Everything you ever wanted to know about building a secure password reset (2012)
troyhunt.com
troyhunt.com
I don't remember if i answered "88 Oldsmobile Cutlass Supreme," "1988 Oldsmobile Cutlass Supreme," Cutlass Supreme," "'88 Cutlass Supreme," "cutlass supreme," "1988 Cutlass Supreme," "Oldsmobile" or any other variation or misspelling. I don't remember if i had to tweek my answer to fulfill your dumb requirements (my favorite teacher has a special character in her name! Or the answer is 3 characters long and you have a minimum of four! My elementary school is numbered) I remember what street I lived on in middle school NOW, but I'll probably forget it in five years, I routinely forget much more relevant things. On top of that maybe I just don't want to tell every website I use who my childhood crush was. There's also the problem of most "secret questions" that are available being irrelevant for X% of the population. (ex. loners and people who didn't have a stable home life... they rarely include stuff like "who was your foster mom when you were 8?" Even the international crowd could have trouble with most questions.)
I'm old enough and have enough online accounts (I have 246 accounts saved in my password manager) that i now just write "fuck you" for all the answers and put 'all answers fuck you' in my password manager. Because these questions stress me out way too much and I'm constantly bombarded with them. Answering them becomes a major pain point when everyone wants them. I've completely lost it with the damn "[not so] secret questions."
The way I remember passwords is by stringing together random English words with random special characters inserted throughout. This means most of them are 30-40 characters. I find these far easier to remember than my PayPal password, which is arbitrarily limited to a random collection of special characters that must be of length less than 12 (or whatever their ridiculously short limit is.)
If you truly care about the security of my account don't impose character limits.
I feel like I filled up my password memory sometime in the late 90s.
Where would you like to retire?
( ) Miami Beach, Florida
( ) Nice, France
( ) the sky has a long face
( ) Bozeman, MontanaAgreed, the “it’s a bunch of gobbledygook” social engineering hack is a really serious vulnerability.
"What is your favorite color? (Red is not allowed)"
Source : https://digitalsynopsis.com/design/color-thesaurus-correct-n...
PS: 1985 Delta 88 Royale Brougham LS with dark smoke metallic paint, limo tint, more chrome that a Cadillac factory and burgundy velour, and a $20k sound system... what you inherit when your dad is an audiophile and wants a car that could fit 6 dead bodies in the trunk.
Just kidding... your approach is a good start, but use a unique password for each one instead of "fuck you".
(It's not actually 'Fuck You,' but something similar and I do sometimes change it up with a few different simple phrase answers. I did own an 88 Cutlass Supreme [worst car I ever owned], but it wasn't my first car.)
Maybe that should be a security question, "what the worst car you've ever owned?," now THAT'S easy to remember all the times you're stranded on the side of the road, stalling in the middle of heavy traffic, and all the repair bills.
Problem with "other password approach" is "I just put a bunch of random characters in there" becomes a valid response to an overseas customer service rep if you're talking on the phone.
EDIT: Ok, any English word or phrase would work for "other password" just fine. I guess after idk how many years of trying to use the "secret questions" as intended I just get angry every time I see them.
it only makes the the account less secured.
the rule should be, you forget your password, say good bye to your account.
There are accounts where that may not entirely make sense, but a lot of my accounts I would love the option to state "The only way to recover from a lost password is to send a notarized letter via snail mail explaining the problem."
No one but me should be able to touch my digital bank accounts without having to first show up at a bank location with my ID or a signed certificate of death.
"Immediate" password recovery is part of the problem. A lot of our accounts most people don't need to recover the password immediately, especially if the reason they have forgotten is that they haven't needed the service in months.
Also, phone calls and text messages aren't slow enough.
These days I just use 1Password's 4 or 5 word password generation option where it works. "What is your mother's maiden name?" "I answered 'griffin accolade stallion catboat' to that question."
A lot of the questions are dumb, like "Favorite Food?" with a pull-down of 8 or 10 answers.
The amount of money I have in the account is small enough that I have not seriously looked into other options yet. How do people with $5 million in a retirement account deal with the fact that someone could really screw you over by getting into the account?
It might be somewhat difficult to get money out of the account, but if you are just trying to hurt someone, that should not be too hard. Log in. Use a million dollars to buy a bunch of a penny stock and the price will skyrocket as you buy. Then start to sell and keep selling as the price plummets.
Overall, I don't know if there is a perfect solution. Perhaps for banks we should pee-in-a-cup DNA test in addition to other tests. For a porn site we can do a poor mans email reset.
If it was clearly a premium option that you paid good money for, the bank or brokerage could have a smart, well trained person handle this. Charge me more than $100, if that what it takes. I think if you eliminate people that don't live in your legal jurisdiction from defrauding you and make them show up somewhere in person (Russian hacker, Nigerian scams) the likelihood of the fraud happening goes down by 3-4 orders of magnitude.
The magic word is Medallion Signature Guarantee and the mechanism is, basically, "Bank of America is satisfied that we were talking to Bob when we affixed this medallion on this paper and if we were wrong we're good for $500k."
The most likely place one is likely to run into this (assuming a typical-for-HN sort of life plan) is if you accumulate a substantial amount of money in your retirement account and then try to transfer it to a different brokerage.
Another interesting thing is citizenship web site (turkiye.gov.tr). You can buy your password from a postal office. If you forget you have 2 options; postal office or if you provided via your both phone number and email. With this web site you can login to other web sites like "appointment to hospitals" web site.
Furthermore you can login to your turkiye.gov.tr from your bank web site.
I forget to mention that I think if you buy from the new Turkish id cards they give you a password and with that password you can login to turkiye.gov.tr. Hovewer there is a microchip within the id card and I'm not sure how it is used for identification. They sell some devices where you place your id and insert it into the USB and you need to install an application.
Oh, and in Turkey there is user side certificates too. http://www.turktrust.com.tr/en/products/e-signature/
Another option is so called mobile signatures but I'm not sure how they are used. https://m.turkcell.com.tr/servisler/turkcell-mobil-imza
The author is trying to make the point that you shouldn't tell users that their username is invalid in a password reset flow. The author then goes further and recommends obscuring error messages during the login flow as well.
I find this behaviour to be user hostile and not particularly effective at concealing anonymity. Under the same threat model, a suitably motivated third party can simply attempt to sign up with the same username, and you'll definitely have an error message if the user is already signed up (and that's besides the point that just because a username exists doesn't mean the person behind that identifier actually signed up, anyone could've done it).
The author tries to justify their position by calling it a "slight usability tax" and "a small trade-off for an infrequent process", but my very short experience building a consumer oriented SaaS is that:
1. Password requests are frequent, even with ~5k users
2. Lots of people have more than one email address, and frequently forget which one they used for your service.
3. The support burden simply isn't worth the pseudo-anonymity.
Of course if the username can’t be an email then the email address must be required for login, the username is just for display purposes.
Also when doing the password reset you don’t need to tell them their email is invalid, you just send out the email for reseting as normal but have some text at the end saying ”if this wasn’t you blah blah blah...” and ignore it if it’s an invalid email.
And of course there are ways of dealing with changing of email address.
Sure, let's play this out. Assume for simplicity that the username / user identifier is the email address for our example.
---
Someone comes to your site and tries to sign up with `foo@example.com`. The system has never seen `foo@example.com` so:
The system registers `foo@example.com` in a pending state and sends an email link to `foo@example.com` saying "Please click this link to finish the signup flow".
It also responds to the person signing up, saying "We've sent you an email, please click the link in your inbox to finish the signup flow".
---
Someone comes to your site and tries to signup with `foo@example.com`. The system has an existing record of `foo@example.com` and the password does not match.
The system sends an email to `foo@example.com` saying that someone tried to sign up a new account with the wrong password.
It also responds to the person signing up, saying "We've sent you an email, please click the link in your inbox to finish the signup flow".
---
For a system as described, I concede that a third party has no means of checking if an email address has already signed up, the messages they receive are indistinguishable.
However, for this to work, the click-link-in-email step needs to be a synchronous part of your signup flow. I worry what this added friction does to the bounce rate. Although since I haven't measured it, maybe this worry is misplaced. And of course there's the caveat that measuring with statistically insignificant sample sizes in the early days of a product is its own can of worms.
On the other hand, I would think that the bigger problem is people using the same password with multiple sites and the attacker is entering username/password combos as fast as they can. Joe Hacker isn't probably going to look at your Facebook page for where you went to school, what your dog's name is, etc. Unless they're after you specifically.
But my tech support team screamed about it. So, I changed it to send an email to the unregistered address saying
"somebody asked for a password reset to be sent to this email address. But we don't have an account associated with this address. If you need help please hit URL or call PHONE. "
A cybercreep still can't tell from the password-reset page whether the email was correct.
This ruse solved my support team's problem.
Having places where I don't recall if I have an account, and if I do, which of my email accounts it was registered to - this solution would actually make me happy. I recall running into it once or twice in the wild and was always just as happy to get the "we don't have an account with this email message" in either email or immediate feedback. That said, I agree with the poster that sees the actual security of hiding usernames as marginal at best, outside of sites where the mere presence of a user is indicative. ("Johnny, why do you have an account on "ILikeLeadingCommas.com"?!")
There are plenty of ways to be imprecise from an information asymmetry problem but still precise enough to allow someone to follow instructions.
If you aren't validating the email by sending an email that has to be replied to as part of the sign-up process (not after), then you are simply assuming that the email address was entered correctly without an opportunity for the person attempting the account sign up to correct it.
The article above is pretty dated (which is noted in the post), and so leaves out some better options for security that are available today, such as authenticator apps for 2fa. In the context of when it was published, it was an excellent and important stepping stone in security awareness, but working with the tools of the time.
Now, we have better options and Troy Hunt (among others) has covered many of them in separate posts over the years.
CSR: “Wait, what’s your favorite city?”
Me: “jeogusbw378fnsbwxwobp”
CSR: “Is that in Europe?”
The best implementations I see are the ones that allow both phone authenticator apps for the people who don't want to carry a keyfob around or need to log in via their phones, and U2F for people who want their physical factor separate from their phone.
FIDO is the way forward, but having run into Microsoft's hapless first attempt (since they managed to get it to not work in anything except Edge on specific builds of Windows they also made it optional, so it actually can't make your security better. Brilliant) I have less confidence it'll ever be useful to the ordinary person... Still, it does protect my Google account.
That makes phone based TOTP the most secure second factor that is pretty much universally accessible to lay users (i.e. not buying a dedicated second factor device, and most people have smartphones).
FIDO U2F isn't quite there yet in terms of universal support, but its design is definitely promising from a usability perspective. It's one technology I'm willing to hold my breath for.
Most sites/applications today require you to have an email address (whether alongside a username or, increasingly, as the only identifier), and fully pass all verification to your email provider (by providing a password reset). In that situation, having a separate password for that site (and, presumably, one for each new one) seems a bit superfluous -- it should be enough to, instead, just enter your email and receive a unique one-time URL that will log you in if opened within, say, 15 minutes.
Would this system be any more insecure than the present model of email + password + reset link?
https://support.smartbear.com/readyapi/docs/_images/projects...
It is basically a reset token but allows logins instead of loading up a reset form. One less thing to implement.
Secondly, it sounds like you just give auth based on this token so you can re-use your password change screen, but if your password reset screen doesn't ask for the current password it really ought to do so to prevent the risk of left over sessions being used to hijack accounts (e.g. not logged out public machines, stolen cookies, etc).
Your second point is spot on and I do ask for the current password. The temp password also works there. This is counter intuitive but not a security issue as you mentioned. I guess I can just skip asking the old password in case this particular session uses a temp password.
I like reusing the password change form. But there is something more to this. Our logs show that if a user needs a password reset, they tend to need it more than once. So, there is a pattern that some of our users simply keep forgetting their password. It might be the nature of what we work on though, most of our users log in a once or twice a month. That pattern gave me the idea that if they are gonna keep forgetting it, maybe I should not force them to reset. Let them use a temp password every single time.
It’s like what Slack does with “magic login link” stuff where you can elect to receive a login link via email instead of using your password during login. I guess branding it like Slack does might be better though.
It should also mention that after a user changes their password, all login sessions should be invalidated. This lets a user who thinks their account/password may have been compromised prevent an attacker from using prior stolen sessions.
This is accomplished by including a nonce (a "number used once" which is basically just a large random number) in the user record that is also included in the auth session, and verified on each request. It gets set to a new value on password reset, and thus invalidates existing sessions. (The active session issuing the password change should ideally have its value updated to the new value automatically, though.)
Expiring all sessions should definitely be a critical point on anyone's checklist when building a password reset system.
Spotify didn't have this for the longest time and it was insane. Someone could buy a hacked account for $1 and get pretty much unlimited access. Though a special sort of infuriating softwaregore because you had to listen to what they were listening to.
You don't want to take any actions on an authenticated session as a result of actions of an unauthenticated user.
"We similarly also lock out after X failed login attempts."
That is not affecting an authenticated session with the actions of an unauthenticated session; that is affecting unauthenticated sessions with the actions of unauthenticated sessions. You should not cancel logged in sessions because of failed login attempts for the same reason. It is a violation of basic security principles for an unauthenticated user to be able to affect an authenticated session. You open an attack vector, one that can and has been used, and can and has been used to escalate as well:
1. Blow through the login limits on the target user's account. 2. In the interests of "security", you cancel the real life login session because of the unrelated actions of attackers. 3. Wondering what's going on, the users checks their email and see the attacker's well-crafted phishing email about how they need to reconfirm their password because of [security bibble-babble]. 4. Because it's so temporally-related, the user is much more inclined to think it's valid and click through.
That's just one way to exploit it that comes to mind; statistically, that's going to be much more effective than blind emails.
Don't let unauthenticated sessions affect authenticated ones.
I drive in an area with some roundabouts, and a lot of polite drivers. There's a handful of drivers that think they are doing us all a favor when they "upgrade" the yield signs on the roundabouts to stop signs. They're not. You're doing much the same thing; security isn't about going in one direction all the way and being as paranoid as possible and shutting down access at the first sign of trouble. It's about getting the balance correct, because being over-paranoid can open you up to exploits too.
Start collecting IP addresses that the user has typically connected through. It's not OK to block that user from doing a password reset on an account with a new IP, but you could at least do some more internal alerts and secondary human checks (even if after the fact). Do all the other things in the article, but this would save some people.
Another one would be to record in session storage or cookie storage, some randomly generated key, that is permanently recorded on the server. If a browser with any of those keys come back and initiates the forgot password script, again, you can lower the weapons a little after they get in.
Limit the rate of both reset and reset re-email attempts (X within Y).
Email the link that should expire on first use and set an expirable token param to complete the reset.
Required login again to make sure people know their password.
Form POST.
Platform-Agnostic Security Tokens (PAST), not JSON Web Tokens (JWT) for headless API calls.
CSRF (form hidden) token.
Always https. Disable http.
It's really weird to see this being advised. I thought we all agreed security questions are bad for lots of reasons.
If you want to see the bunnies, it works to go the page at archive.org [1] and click the link there.
[1] https://web.archive.org/web/20170819153353/https://www.troyh...
My mother's maiden name was trick cheese lobster
Question: there's no real reason for the hash to be in a separate column, correct? Just that it's different per record?
Discussion from back then: https://news.ycombinator.com/item?id=4280440