Hacker News new | comments | ask | show | jobs | submit login
Everything you ever wanted to know about building a secure password reset (2012) (troyhunt.com)
201 points by colinprince 15 days ago | hide | past | web | favorite | 108 comments



Fuck "secret questions."

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


Even worse are websites/services that impose ridiculous character requirements (you must include 2 symbols, 3 numbers, 5 letters, 2.5 of which must be upper case and positioned at the prime number indices, oh and you have to change your password every 6 months) and then limit your password to 8-12 characters.

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 spent 20 minutes trying to come up with a password for chase.com recently because of insane rules like, you can use more than two characters in ascending or descending order, can't use the same character more than twice. Using a random password generator above about 20 characters, and it's guaranteed to break one of there inane rules; let alone if you want to use a pronounceable passphrase that's simply long. It's really aggravating that big companies are some of the worst at this security stuff.


I use Bitlocker and I can set limits/conditions on pwd generation which is then saved under a master pwd.


Which Bitlocker is that? I'm only familiar with drive encryption by Microsoft. Do you mean Bitwarden?


Opps you're right....BitWarden

I've tried the random word string concept but I can't remember those ones either.

I feel like I filled up my password memory sometime in the late 90s.


It does make sense to impose some sort of upper bound (only so someone doesn't try and DoS you with a crazy long password), but 13 characters isn't going to bring a server to its knees.


I look at security questions and answers as a challenge and response. I stopped answering them logically when I realized I don't have to. So the answer to "Where would you like to retire?" might be "the sky has a long face." I won't ever use them unless resetting a password, and I won't be resetting a password unless I mess up synchronizing my password manager. Except when I do need them, because the dip shit that operates the site doesn't "recognize" the computer (browser session) I'm using. That crap needs to go.


This is fairly effective until the day comes when you use this method on a system that tries to be even nicer about password recovery... and presents your answers in a multiple choice context.

Where would you like to retire?

  ( ) Miami Beach, Florida

  ( ) Nice, France

  ( ) the sky has a long face

  ( ) Bozeman, Montana


What site is doing this, giving your password away?


TransUnion, for one.

Is TransUnion doing this with fill-in-the-blank security questions? Or are you referring to indetity verification questions base on credit report data?

I just generate more passwords for the security questions. Since I’m using a reliable, backed-up password manager, my primary concern is protecting my account from would-be hijackers, not resetting a potentially lost password.


Yes, because there is no way I'm answering what city I was married in. It is public record. A password-like "nonsense" answer is the only way to go.


The one thing I try to do is make sure whatever password generator I use for these produces pronounceable passwords in English that are relatively easy to spell, because so many of the places that want these really mean "Phone password".


1Password integrates with the iPhone's built-in password manager, so I'm never stuck typing in passwords anymore.


The issue isn't typing them. The issue is that many "Security Questions" are secretly "Phone Passwords" because customer service representatives can see them in plaintext and will ask you them if you ever have reason to call them over the phone. Making sure that they are pronounceable (mostly) English words avoids some of the potential awkwardness of reading them out of your password manager over the phone, even if they are intentional random gibberish. It also partly avoids the social engineering trap of "it's just random garbage" because at least if it looks like words a customer service rep may still ask for them anyway rather than not bother to one-at-a-time review a series of random characters.


Ok, gotcha. 1Password can also generate passphrases from dictionary words.

Agreed, the “it’s a bunch of gobbledygook” social engineering hack is a really serious vulnerability.


> Or the answer is 3 characters long and you have a minimum of four!)

"What is your favorite color? (Red is not allowed)"


Also 'tan','oat','yam','jam','ash','fog','ink','oil'

Source : https://digitalsynopsis.com/design/color-thesaurus-correct-n...


But TanOatJam is not bad.


That only has ~23.72 bits of entropy.

I use random passwords for reset questions because they're often the Achilles' heel that people drive around.

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.


Interesting! Do you use astura everywhere on the web?

Just kidding... your approach is a good start, but use a unique password for each one instead of "fuck you".


No, I usually generate a new username per site with a script if a username is required. Either that or use a name generator to pick a random Firstname_Lastname username.

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


You're right about the other password approach, it seems like the best alternative is a passphrase.


Yeah. a secret answer is just a secondary password with extra restriction (have to be actual words) and you also get a hint.

it only makes the the account less secured.

the rule should be, you forget your password, say good bye to your account.


Or "show up somehow in person". We have all of this physical infrastructure we could take advantage of for critical accounts: IDs, notaries, passports, post offices, etc.

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.


I feel the same. As a workaround I keep my answers in the password manager notes. Thinking about it it would be more secure in this case to lie.


Apple still does this. So does United Airlines. Many sites do this and I think it reflects badly on the company.


Just put another password in that box!


Problem with that 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.


I've successfully responded something like "It's a 25 character random string beginning with A#fx and ending with ^tx% - would you like me to read the whole thing out?" to customer service reps. (I've never tried to see if anyone will give me access to an account just by saying "a bunch of random characters", but I wouldn't be surprised if they did...)

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


That's neat that 1Password does that. I tend to do something like "Clark Dark Bark Park" for "First school?" and record it in LastPass's notes.

A lot of the questions are dumb, like "Favorite Food?" with a pull-down of 8 or 10 answers.


https://iancoleman.io/bip39/ is similar. Press the GENERATE button and grab the first few words off the seed.


OSX Keychain has a "memorable" feature for password suggestion (e.g. getup3_gulag). 1Password has a "words" type of password (e.g. ancestor-dissent-rubdown). I suspect other password managers have similar. That's what I use in this situation.


Also, the classic Diceware lists are great for these. Print one out and roll physical 6-sided dice for the full experience.

http://world.std.com/~reinhold/diceware.html


Good point.


In that case, a series of random dictionary words can suffice.


I sure wish my brokerage would allow me to turn off all online password reset options. They have an office near to me. If I forget my password, I would like to have to go to the office with my passport to reset it. This person should be high level and well trained so that social engineering is unlikely to work on them. I would be happy to do this and would prefer if they charged me $100 to reset my password this way. I don't day trade so I don't need a way to instantly reset my password. Many years ago I reset my brokerage password online and it was way to easy to do.

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.


I've actually wondered the opposite. If someone is charming enough, and has done some preliminary research on the bank's in-person screening, could they bypass security with something as little as a fake ID?

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 I forget my password, I would like to have to go to the office with my passport to reset it. This person should be high level and well trained so that social engineering is unlikely to work on them." Passport and well trained.

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.


This is an option at many financial institutions and often required above a certain level of transaction, but retail customers don't hear about it quite so often because it's in the general category of "If you have to ask, you can't afford it."

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.


I believe that DNA tests fail the same reason that eye scanners and fingerprints do: they are not private. Almost anyone can get access to any of those 3, and then they just need to figure out a way to use it on the system.


Is it really that easy to forge someone else's DNA and bring it to a testing facility?


DNA is a replicator molecule. You don't need to forge it, just get a tiny sample and it will make as much as you could ever need with gear found in any high school lab.


The bank manager needs to watch you pee. jk


In Turkey 2FA is mandatory for online banking. When you renew your SIM card you cannot login to your account. You need to revalidate your identity with additional steps. I think there is an integration between banks and mobile operators because when you renew our SIM card you don't receive SMS code for login even though the phone number is same.

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


Right now I cannot use a payment web site (epay.bg) in Bulgaria because my 10 years old user side (that you install in your web browser) certificate has expired. According to the new rules I need to go to a digital certificate generator company in person with my identification card and buy a user side certificate.


I once knew a person that had millions of dollars in liquid banking accounts at one institution with their username and password saved in a contact on their phone!


I disagree with the section titled "Username enumeration and the impact on anonymity".

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.


If the username could be an email address (or the email address is a required field on signup) you don’t have to pass back a message saying that the username is already taken. You simply let them go through the flow and do verification of the email address by emailing and requiring clicking on a link, and if they are already signed up send a message saying someone tried to sign up with your email address.

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.


> If the username could be an email address (or the email address is a required field on signup) you don’t have to pass back a message saying that the username is already taken. You simply let them go through the flow and do verification of the email address by emailing and requiring clicking on a link, and if they are already signed up send a message saying someone tried to sign up with your 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.


Often the message is "If there is an account with that email, we'll send you a link". The idea is that you don't want to confirm that there is an account because it might be someone testing to see if there is one.

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.


Don't most signups require clicking an activation link sent via email anyway these days?


I built a password reset system that didn't tell the requestor whether they gave an unregistered email address. It just said, "look in your mailbox." Because, avoid telling cybercreeps anything useful.

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.


> 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"?!")


I've seen variations from "look in your mailbox" to "If there is an account associated with this email address, you will receive instructions."

There are plenty of ways to be imprecise from an information asymmetry problem but still precise enough to allow someone to follow instructions.


so I receive an email (possibly more than once) from info@spamfromtheantipodes.com telling me someone confessed not to know the password associated to my email address because I don't have an account there? for the email-recipient the cure might feel worse than the disease


Technically there doesn't have to be live email validity checks on the sign up page- an email with the continue your signup with this link could be made available. OR an email saying you already have an account, do you need to reset your password?


If you allow the full signup with the email confirmation after, then you are potentially sending the confirmation email to the wrong person. I have gotten sign up confirmations from other people using my email address. I have sometimes confirmed the registration, used the password reset to take over the account (since they use an email for the reset), then cancelled the account.

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.


I really think secret questions are garbage. They grant minimal extra security for the cost of a huge hassle for customers. But the worst part about them is requesting and storing a significant amount of highly personal data. The likelihood of this data being breached and used against you is probably much greater than the security improvements it grants. Requiring many pieces of personal data to sign up for every fly-by-night web application is short-sighted and inconsiderate.


I agree completely.

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.


Especially when websites use secret questions as a means to reset second factor..


Another criterion for a good security question: make sure everyone actually has an answer. I use a website that forces me to answer the following question: in what month was your first child born? It boggles my mind that someone at this company could fail to consider the possibility that a user of their site might not have children.


That's kinda funny to me. For people like me (and likely a lot of others that browse this site) the answer to how many children you have, is clearly "@#T%FGDw34dsd$"


Giving answers like this over the phone to customer services reps is always a good laugh.

CSR: “Wait, what’s your favorite city?

Me: “jeogusbw378fnsbwxwobp”

CSR: “Is that in Europe?


Huh. I only have "monkey ((( banana B4N4N4 banana" kids. I should probably switch to an automated child enumeration reminder program, to keep track of how many kids I had when I signed up for different accounts.


Or that this information is known by other people too.


I’ve similarly encountered mandatory security questions making US-specific cultural assumptions that simply do not translate internationally. “Name of your prom date” and “Favourite middle school teacher” for example.


I have a pin code that I use to answer any and all security questions. I feel just as (in)secure using it versus the real answers, and I don't have to remember which "real" answer I chose when setting it (or whether I capitalized any words, etc.). I suppose I should start using random, incorrect answers and keeping them in my password manager, but I haven't got around to that.


That's exactly what I do. I generate "passwords" for the answers and record them in the password manager.


This particular site forces me to choose a month from a dropdown menu.


Or worse. Dead children.


This is really good stuff. I think the only thing I'd add is that, if you're building a login system anew, you should do 2-factor, and you should not use SMS codes. Use phone authenticator apps (time-based OTP's), FIDO U2F, heck, even Smartcards if you're paranoid.

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.


OTPs are phishable. If you worry about SMS codes, you shouldn't accept OTP either, bad guys are just going to socially engineer your user into giving them a valid code.

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.


Phone based TOTP's are vulnerable to real-time phishing, but they still require you to sit there and enter the number on your phone. It still has to be your phone. That's not ideal, but that's substantially better than SMS where someone can take your phone number and your second factor is gone. No real-time requirement.

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.


I've been wondering how even having a password at all might be an antiquated feature.

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?


Tumblr already gives you the choice to login via password or via a link sent to your inbox, although i have to admit i have only used this once to try it out - i am simply used to my password manager filling out the form in one click and i dont like to switch to my e-mail program everytime i log into something.


If you play this idea out to its extreme, and automate most of it, you get the first version of OAuth.

https://support.smartbear.com/readyapi/docs/_images/projects...


How would you get that to work simply in a mobile app login flow?


IIRC, slack does (or did, ~3 years ago) exactly that. Either the email link is structured to cause the mobile OS to open the app, or the link leads to a page that then presents a link that opens in the app. In either case the link(s) contain a token that's valid for one use.


My current approach is to send an email with a temporary password which works for a single login and can be used to change the password. Original password still works. Temp password expires in 1 hour.

It is basically a reset token but allows logins instead of loading up a reset form. One less thing to implement.


Firstly, does your approach still invalidate the original password? If not that's really counter-intuitive. If I click a reset password button I want my password reset.

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


Well the idea is that you do not click a reset password button. You click on a forgot password button so this gives you a temporary one to use.

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.


Good, extensive write up. Note that correctly hashing passwords is a topic in itself and the short answer IMO is: use bcrypt.

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


Or execute sql "update active_sessions set expired_at = now() where user_id = $1"

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.


If you do not have a server side session store, only option is to use a nonce of some sort though.


Or use a access/refresh token pair


I really appreciate systems that allow me to rotate passwords without invalidating existing sessions — essentially, treating passwords more like tokens (as in OAuth, or Google app-specific passwords). Of course, it’s critical to have a “reset my sessions” link, but sometimes I just want to change my password, and other times, I just want to revoke existing sessions.


For the extra conservative, rotate the nonce when the reset is requested.


That opens an attack vector where I can keep someone off a site by repeatedly requesting a password reset.

You don't want to take any actions on an authenticated session as a result of actions of an unauthenticated user.


Yes I do. Sometimes the medicine is unpleasant but necessary. For many services, a malicious denial is better than an active compromised account, both in the material consequences and the opportunities for tactical management. We similarly also lock out after X failed login attempts.


Requesting a blind password reset is not a "compromised account".

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


Thanks for your remarks, but you've made some profoundly incorrect assumptions and raised contextually variegated guidelines to the status of axioms.


There are some slight enhancement that could be made, but would require gathering some additional info about your users:

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.


Password storage (hashes only): PBKDF such as argon2i and salted.

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.


Please don't use security questions: http://lucb1e.com/?p=post&id=65 (coincidentally also from 2012)

It's really weird to see this being advised. I thought we all agreed security questions are bad for lots of reasons.


The fluffy bunny option does not work for me, in either Firefox or Chrome on my Mac. Instead of replacing the image on the page, it just reloads the whole page with the boring humans.

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


Nobody said the answers to test questions have to be truthful or make semantic or syntactic sense.

My mother's maiden name was trick cheese lobster


> the password is hopefully accompanied by a salt, each of which sit in their own columns

Question: there's no real reason for the hash to be in a separate column, correct? Just that it's different per record?


Correct. Many hashing functions designed for password hashing build the salt directly into the output string, in order to make it difficult to accidentally hash passwords without using a salt. On the other hand, if you're just using a bare hash function, you may find it convenient to store the salt in a separate column, if only to save yourself having to split on a separator character / character length in your application logic.


Yeah, that's what I was I thinking. Bcrypt does that, or at least the implementation I'm familiar with seeing in Rails. The sentence threw me off there for a second. Thanks for the clarification.


A good article but needs "(2012)" in the title.


Good catch!

Discussion from back then: https://news.ycombinator.com/item?id=4280440


Maybe a feature request to save you some work. On submission, based on url, the site automatically lets the submitter know of prior submissions and if they choose to submit anyway, then (if they do) the first comment is an auto comment with links to previous discussions. Could also add a year to the lookup and have that gets auto added to the title if not already present.


Everything you need to know about building a secure password reset: Cryptographically secure universally unique id -> email.




Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: