top | item 8683003

“Invalid username or password” is a useless security measure

413 points| kevinburke | 11 years ago |kev.inburke.com

182 comments

order
[+] andrewstuart2|11 years ago|reply
I think the real lesson here is that if emails should remain secret you should not indicate upon signup whether or not a user exists with that email.

Always send an email.

If that user already exists, make sure the email says "We noticed you're trying to sign up again. If you didn't do this, someone else is trying to sign up for you." If that user doesn't exist, send them the typical signup message.

The author has some great security tips in the "what should I do instead" but I don't think the instead portion is accurate. Keep private information private, and make access to public information as easy as it should be.

If emails are public, shoot, use a websocket connection to style the login field in real time and show the user whether or not the email they typed is valid.

[+] snowwolf|11 years ago|reply
Please don't always send an email. A malicious person can now start signing up every day with a bunch of emails resulting in users who do have an account receiving an email from your site daily/hourly saying "we noticed you're trying to sign up again". At which point they become annoyed with your service and either unsubscribe or delete their account.

Hotmail do this everytime someone tries to reset my password which happens almost daily as I have what turns out to be an account name that is in demand and it's really irritating. And there is nothing I can do to stop someone attempting to reset my password - I have 2 factor switched on so they won't be successful.

Of course you can add more logic in to try and be more intelligent about when the emails are sent, but most sites won't get this right when they can't even store passwords correctly.

[+] crumpled|11 years ago|reply
Forcing the user to interact with an email client during the signup process before they've confirmed the availability of a username might be good for security, but it's a horrible way to gain users. That's a very high friction process. I generally agree with this comment, however.
[+] makmanalp|11 years ago|reply
This doesn't really work that well, I realize - when users mistype their e-mail, they get their registration sent to some random address, and they get zero feedback on what went wrong. From their perspective, the registration worked and they just got no e-mail. Bad experience.
[+] slg|11 years ago|reply
Security is all about trade-offs. Sending emails puts a bigger barrier between signup and first sign in. It is probably a better business move to slightly inconvenience some existing customers rather than slightly inconvenience all potential new customers.
[+] kevinburke|11 years ago|reply
Thanks for this. I updated the post to add this as a possibility.

This adds more friction in the signup process than I'd be willing to accept, but it does solve the information disclosure problem.

[+] higherpurpose|11 years ago|reply
If you're only giving the message when the username doesn't exist, wouldn't that mean the attacker would know when the username does exist?
[+] superuser2|11 years ago|reply
> if emails should remain secret

This is important. It is not always necessary or appropriate to try to maintain the secrecy of otherwise public, directory information (like email addresses). Unless you are, say, FetLife, it doesn't actually make that much sense to hide the fact that [email protected] has at one point signed up for your service.

On the other hand, associating [email protected] with posts he thought were anonymous is an enormous violation.

[+] Sarkie|11 years ago|reply
Hotmail used to do this and still does, so easy to find if an email is real.

Email is found, password is not correct. Email unknown.

[+] tacostakohashi|11 years ago|reply
Leaving security aside, "incorrect username/password" is still the more correct and useful statement.

Consider the case where you mistype your username (email). For sites like amazon, gmail, hotmail, yahoo, twitter, etc, it is entirely likely that the mistyped username is somebody else's valid username, you typed the password correctly, and "incorrect password" would hide the problem.

[+] drzaiusapelord|11 years ago|reply
I've worked with a CRM product that allowed non-unique usernames. That's right the usernames could be duplicated, so we had like 10 jsmith's. It would parse the username/password combo, and if one matched, that's who you logged in as. I never got to test what happened when jsmith had the same password as another jsmith. I'm sure the results would have been terrifying and hilarious. Apparently, the history here is that it used to log people in using their email as their only username, but someone here didn't like that and the vendor tacked on this half-assed solution. So you email is your unique identifier but its not used during login.

I suspect there's a lot of poorly written software that still does stuff like this. The message is still valid in these cases as well.

[+] mikeryan|11 years ago|reply
This seems like a messaging problem?

"Password does not match our records for username/email XXX. Please check that both password and username are correct."

Responding to below This reads to me like a more verbose version of "Incorrect username or password."

Note this version is not wordsmithed and could probably be done better but the goal and inherent difference of this to the original is to let the user know that the username exists and that its the password which does not match.

[+] rrrx3|11 years ago|reply
That statement doesn't help the user fix a problem. Either you tell the user that one of the items is incorrect - "This password does not match our records" or "This user name does not match our records". Simply stating "Incorrect username/password" isn't sufficient enough information to prevent the user from making the same error (or even a different one) again.

Here's what I tell the developers I work with: Design for the users, not for development ease. This pattern has been successfully implemented by literally hundreds (thousands? hundreds of thousands?) of websites, so there's no excuse for trying to cut a corner and try to concatenate use cases. Either the user name is right and the password is wrong, or the user name is wrong and the password doesn't matter, or both are wrong and through some miracle of absolute unicorn user error they've managed to log in to someone else's account - at which point you have a different issue altogether.

[+] paublyrne|11 years ago|reply
More likely, people won't forget how to spell their email address, or make a mistake in typing it that isn't immediately obvious; they might not remember which of their emails they used to sign up, though, even if they only have a couple. No one else can sign up with an email address that belongs to you.
[+] Houshalter|11 years ago|reply
Well you can at least inform the user that the username is incorrect if there is no user by that name.
[+] weinzierl|11 years ago|reply
"You don't exist. Go away." is my personal favourite.
[+] Domenic_S|11 years ago|reply
I actually have two amazon accounts with the same email address (username), one has prime and the other one doesn't. Sometimes I type in the 'other' password and get the non-prime account and get confused.
[+] pbreit|11 years ago|reply
"is still the more correct and useful statement"

No, it is usually incorrect and it is much less helpful than identifying which is incorrect.

"it is entirely likely that the mistyped username is somebody else's valid username"

No, that's highly unlikely.

If the email isn't in the DB, just say so. If the password doesn't match, just say so.

[+] tetrep|11 years ago|reply
>99.9% of websites on the Internet will only let you create one account for each email address. So if you want to see if an email address has an account, try signing up for a new account with the same email address.

While this is true, it's perfectly reasonable to require a captcha before allowing a new account to be created; greatly limiting the speed at which an attacker could enumerate emails. While it's not going to stop targeted attacks, it will mitigate mass brute forcing of weak passwords.

Regardless of the ease of username enumeration, all of the author's points about what to do are great for most sites. Rate limiting with exponential backoff and 2fa are some of the cheapest and most effective means of increasing the security of your app's authentication process.

[+] volkangurel|11 years ago|reply
It's only useless if the website reveals the username elsewhere, but that doesn't have to be the case.

Consider the case when the primary usernames are always emails (many sites do this), and signing up for an account is simply done with entering an email and a password. Then, when someone submits a signup form, the website can:

- Check if an account with the email exists, and if it does, whether the given password matches the existing one.

- If both are valid, log the user in, optionally showing a message saying “there was already an account with these credentials so we logged you in”

- If an account with the email does not exist, or if it exists and the password doesn’t match, return a message to the user saying “please check your email and follow the validation link”. The user can’t tell if the email exists or not.

In the backend:

- If the account did exist, send an email to the user saying “someone tried to sign up for an account with your email, please let us know if it was you. and here’s a way to reset your password if you forgot it”.

- If the account did not exist, send an email verification link, which then redirects to a page to complete the user signup

Same with password resets, the success message can always say "check your email".

There are ways around revealing the username. But I agree, only doing this in the login page is useless.

[+] Someone1234|11 years ago|reply
> Consider throttling invalid login attempts by IP address or subnet.

Oh hell no.

First off that is completely ineffective. Botnets are common and inexpensive. But worse still a lot of users often share a single IP (e.g. university dorms, businesses, public wifi, etc).

I agree with the first part of this article (i.e. that it is trivial to "prove" a username is valid, and that worse error responses aren't accomplishing anything). But that advice is poor.

> Check submitted passwords against a dictionary of common passwords (123456, monkey, etc) and ban that traffic extra hard.

That seems like a lot of engineering work. Plus the workload of loading up a dictionary and doing a lookup upon each login is resources that frankly could be better used on a slower hashing algorithm (to slow logins and make stored hashes stronger).

> Exponential backoff (forcing attackers to try again after 1, 2, 4, 8, 16.. seconds) is useful as well.

Just open a spreadsheet and determine how long it would take to test 1500 passwords. 1500 is a "short" dictionary of common passwords. Even a 1 minute delay after each 2 attempts (or 2 minutes after 4, or 4 minutes after 8, etc) means 12.5 hours of attempts.

I like to set the attempts really high with an equally high lockout. So no normal user will see it. Most users do a password reset after the fourth or fifth attempt, so if you set it on 8 attempts with a 4-6 minute lockout then the majority of users will never run into it.

Instead of focusing on these kind of hacks why not just:

- Set no maximum password length (250+ characters)

- Set the minimum to at least 6 or 7

- Get a password score widget (e.g. "weak" "normal" "secure"), traffic light, to encourage better behaviour

- When a password is set check it isn't in a common password dictionary (a lot of score widgets integrate this!)

- You can use Javascript to check a password dictionary as it isn't a site-security feature, and anyone who goes out of their way to bypass it only has themselves to blame.

- Agreed on 2F, Google Authenticator is trivial to integrate. The only remotely "hard" bit is generating the QR code and a lot of libraries exist for that express purpose.

- No clue how you'd integrate LastPass...

- Account Alerts are extremely useful. As are admin alerts. Too many sites get no warning when a lockout occurs, it is pathetic.

[+] ernesth|11 years ago|reply
>> Exponential backoff (forcing attackers to try again after 1, 2, 4, 8, 16.. seconds) is useful as well.

> Just open a spreadsheet and determine how long it would take to test 1500 passwords.

5.557 * 10^443 average Gregorian years.

[+] tracker1|11 years ago|reply
I have to agree with the parent here... There are other ways to add security, and having an obscure error message doesn't really improve things by as much as the error message can cause real users to go down the wrong path.
[+] TheLoneWolfling|11 years ago|reply
Exponential backoffs also have the problem that it makes it far easier to lock someone out of their account. Or rather, it makes it possible to lock someone out of their account for an arbitrary amount of time.

> When a password is set check it isn't in a common password dictionary

I agree with this with short passwords. But for passphrases? No. I find it rather frustrating that (ex) diceware passwords are often rejected as too insecure or flagged with a nasty warning.

[+] ajanuary|11 years ago|reply
> Just open a spreadsheet and determine how long it would take to test 1500 passwords. After about 58 attempts the sun would have exploded. After 1023 attempts my spreadsheet application can't cope with numbers that big.
[+] why-el|11 years ago|reply
None of the author's recommendations conflict with the practice he is advocating against.

I think websites say "Bad combination" not because usernames are treated equally with passwords, but because you don't have a choice but say that.

If I tell you that your username is incorrect, am I telling you your password isn't? This would be silly, because if the website is new and I know a password is correct, then I can either find the username out there (if the website is social), or pretend I forgot my username and have them give it to me.

Assuming that's not what I am saying, then the user is surely to have a bad experience anyway, since they will need to figure out a wrong username, and then in the worst case, a wrong password. When you say a "bad combination" you at least eliminate a possibility to mislead them into thinking only one of their credentials is wrong.

[+] masklinn|11 years ago|reply
> I think websites say "Bad combination" not because usernames are treated equally with passwords, but because you don't have a choice but say that.

Of course you do.

> If I tell you that your username is incorrect, am I telling you your password isn't? This would be silly

Of course it is, a password is checked against a username, not against the whole database. If the site is telling you the username is incorrect it's telling you just that: the username is incorrect. It wasn't able to go any further and check the password since it has no idea which password it should check for (or even, if you're correctly storing passwords, which salt it should use for the password check). Your criticism doesn't even make sense.

[+] Evolved|11 years ago|reply
If I tell you that your username is incorrect, am I telling you your password isn't? This would be silly, because if the website is new and I know a password is correct, then I can either find the username out there (if the website is social), or pretend I forgot my username and have them give it to me.

Not exactly. Multiple users could obviously have the same password but not the same username. Telling an attacker that the password is correct doesn't narrow down the possible user names it could have, <n, thus still meaning the attacker must theoratically try all valid username combinations with that password unless they have some way to narrow it down.

[+] spion|11 years ago|reply
"Sorry, we don't have a <name> in our database" isn't misleading. If the user enters an incorrect password too, the subsequent message "Invalid password for <name>" will let them correct it.
[+] tracker1|11 years ago|reply
If the username is wrong, and you don't tell them, they will spend several tries on passwords that will never work.. because the user is invalid.

I have a number of sites I don't use often, that I wind up having to do a password reset on to then find out I'm not even using the right username... there was literally no gain from this... Any hacking attempt can do the same to determine if a username was valid or not.

It's making things easy for machines to do harder for people to do, which is the wrong approach to security.

[+] 0xffff2|11 years ago|reply
Even simpler than trying to sign up for a new account, many sites will tell you if you enter an unregistered email on their "forgot password" page.
[+] jdmichal|11 years ago|reply
Except that entering a registered email will likely result in the legitimate user receiving a password reset email that they did not request, thus immediately raising suspicions that someone may be attempting to access their account. Using the signup form is a much better approach.
[+] fmx|11 years ago|reply
Some sites don't. They instead say "if an account with that email address exists we've sent you an email with the reset link". That seems like a nice touch, but it's pointless if you can still find out that a given email address is a registered user in some other way (such as by trying to sign up with it). So it's just another variant of the "invalid username/password" message.
[+] rcthompson|11 years ago|reply
Yes, but that also alerts any valid account with an unexpected password reset.
[+] mlrtime|11 years ago|reply
It is very annoying that visiting a site that you know you have an account on but cannot remember your username. The rate limiting feature seems to solve most of the issues with giving the user a chance at some feedback.
[+] tokenizerrr|11 years ago|reply
They should allow login by email instead of username
[+] rdl|11 years ago|reply
Thinking this is only about security is shortsighted, IMO. There are cases of typo-ing the email address, or entering a non-standard email address, which happens to match another.

[email protected] -> [email protected] probably would have some benefit to UX in saying "email address does not exist", but [email protected] vs. [email protected] both exist.

What I'd probably recommend instead, if you do decide confirming account creation status makes sense, is judging by cookie or IP. If 10.10.10.10 has previously logged in as [email protected], and I enter [email protected] instead, it might make sense to poke on the email; if I enter [email protected] and have an incorrect password, maybe suggest bad password. (of course, if you have a cookie, you might as well pre-fill the login; if you have an IP match, probably not).

The security tradeoff here exists but isn't huge. There are definitely cases where the user benefit (and thus reduced bounce rate) of suggesting error in username or password would make sense. The biggest security issue is confirming "does this account exist at all?", because email addresses tend to uniquely identify users, and you need some other mechanism to prevent this -- either automated (captcha would work) or targeted (in which case it's quite hard).

I'm actually in favor of per-action security checking vs. "logged in or logged out, all or nothing".

[+] ademarre|11 years ago|reply
This problem is often referred to as user enumeration, which seems like a misnomer to me.

Whatever you call it, it's good to keep in mind that Google, Apple, Facebook, and Twitter are vulnerable.

The most interesting facet to user enumeration is privacy. If Alice knows Bob's e-mail address, is it right that she can easily check with Carol's web system to see if Bob has an account with Carol? This is like calling a hotel and asking if a certain person is staying there. It leaks information confirming that two parties have a relationship.

What makes the privacy aspect especially interesting is that user enumeration is a bigger problem for small websites than for the Googles and Facebooks. This is because it's not much of a privacy breach to be able to test if a given e-mail address is on Facebook; big whoop, almost everyone is. But it's a much bigger breach to be able to test if a person is a customer of an illicit service. Most systems sit somewhere between those two extremes, and each needs to decide whether to prevent user enumeration.

The main point the author tries to make is quite matter-of-fact: If you are going to try to prevent user enumeration, then you have to do it for real, which usually results in less friendly account creation and password recovery systems.

[+] allendoerfer|11 years ago|reply
The article does not point out, that not teling visitors which of password and username were wrong on login pages is a useless measure, it shows that there is a second way to find out correct registered email addresses on most platforms (by trying to register them).

This can be easily fixed by sending email conformation tokens prior to creating the user account and informing users in this email, in case they already have an account.

[+] MAGZine|11 years ago|reply
I don't agree with the author's premise wrt to usernames.

Often, you will login with a username, but the password recovery form will only accept an email. You might be able to correlate these two if you have a lot of data from other, external attacks, but unless if I noticed correlation between recovered passwords and account break-ins, I wouldn't worry about this.

There's a security tradeoff, but sometimes security must be risked in the name of functionality, or you'll have a lame product. Or, you can have both security and functionality, but to the detriment of UX.

Take leaderboards for example. If you have a leaderboard for your app/game, you'll expose user's username (and thus, sign-in name, as is often the case). You could mitigate this by: having a separate login name (ala steam), or using an email (which exposes people to the recovery exploit), but it doesn't make the UX any better.

In the end, I'd say trying to protect against username/email guessing attacks is probably unnecessary. There are better ways to approach security.

[+] Sami_Lehtinen|11 years ago|reply
Alternate view, I hate sites which require login & password, especially to only view content. I try to ignore every such site, because those are designed really badly. As well as I don't get it what's the correllation between email and registration. I don't want to give my email, nor I want to register. If I need to give email, I can give any random temporary email. Signup procedures on many sites are horrible. Best sites do allow at least accessing content without these hindrances. Logging in, especially on mobile, is painful anyway. Using some kind of federated login is privacy issue (in most cases), so it doesn't solve anything either. For lulz, how about just PGP signing nonce? They can verify it against my public key. PGP also allows me to easily create as many parallel identifies with strong authentication as I want to.
[+] darrhiggs|11 years ago|reply
The article misses the point that on many sites this is not a security feature, more a privacy one. I have used the 403 http status rather than 401 in the past for this exact reason.

RFC 7231[0] suggests something similar

"An origin server that wishes to "hide" the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found)."

with RFC 7235[1] suggesting the use of 403.

"A server that receives valid credentials that are not adequate to gain access ought to respond with the 403 (Forbidden) status code […]."

[0] https://tools.ietf.org/html/rfc7231#section-6.5.3 [1] https://tools.ietf.org/html/rfc7235

[+] xborns|11 years ago|reply
As many have said if you simply rate-limit with captcha and block it complicates checking against all emails via bots etc.

This rule doesn't apply well to say the majority of b2b systems that don't have account creations public. Thus now I can phish for users and send them targeted oh reset your password here emails because I harvested them from some other hack. Remember it is not always the password that is the weak link it is the user as well.

So calling it useless is shortsighted, yeah for many basic sites it is simple to say yeah tell them what is wrong. That is why they created the picture login to go with the email to ensure you are logging in on the right site. If anything you aren't sure try forgot password with your email.

Source: Real experience building auth systems for large corps.

[+] Evolved|11 years ago|reply
I'd be concerned that if hackers found out their login attempts were increasingly rate-limited (2 seconds, 4 seconds, 8 seconds, etc.) then they would just use that instead as a DoS attack and run that rate limit up to weeks or months if possible.

Send email to email address on file stating "someone has attempted to log in to your account multiple times..." only after multiple unsuccessful attempts.

What about a flat rate-limit of something like 30 seconds (or something similar) which is low enough that a user likely wouldn't be that irritated by it, won't be a severe DoS and is likely sufficient enough to hinder illegitimate login attempts?

[+] ColinDabritz|11 years ago|reply
Interesting premise. I think the original behavior is partly correct. The combination of user name and password doesn't match. Either one could be incorrect. Say my usual login is [email protected], and I do know my password. If I try to log in as [email protected] with my correct password, it is conceptually NOT the password that is incorrect. The user could legitimately make such typos, and should probably check both fields.

On the other hand, this is a reasonable argument for prompting on invalid user names, e.g. "This doesn't appear to be an existing account, make sure you typed it correctly, or try our [sign up page]".

[+] hobarrera|11 years ago|reply
Indeed, the assumption that usernames should be secret is stupid and senseless. Passwords are meant to be secret. Emails and usernames are not. Heck, emails would be public, were it not for spam issues.
[+] userbinator|11 years ago|reply
How about just changing the signup process to "send us an email from your email address" and then you receive a reply with the further instructions/link? It would make it impossible to discover whether a user has signed up without gaining access to his/her email account. You could easily make this more abuse-resistant (and reduce the inevitable spam) by generating a temporary session ID and embedding it into the subject of the mailto: link, or even use temporary email addresses to receive registrtion requests.