
“Username or password is incorrect” is bullshit - carlchenet
https://hackernoon.com/username-or-password-is-incorrect-is-bullshit-89985ca2be48
======
pornel
The right answer isn't a blanket "sites should do this super-secret e-mail-
only shuffle and not tell you anything".

First, you should define your threat model: which information is considered
secret and which isn't, and treat any violations as security vulnerabilities.

If usernames are public by design, then don't hide them in one form, and
expose in URLs elsewhere on the site.

If exposing who's registered on your site really is a threat, then by all
means have a weird registration (and password reminder) that doesn't tell
whether it worked or not. But if your site is for cookie receipies and you
don't consider exposing who's a fan of cookies a privacy violation, then just
use most helpful messages you can.

~~~
sp332
Right, for example if you run an email service, your usernames (addresses)
should be hidden. That's because a spammer could use your login page to find
valid usernames and then send spam to them. They don't have to guess passwords
to cause damage.

~~~
koolba
They could also use your signup page to attempt to create an account for
user@example.com. Since you can't allow duplicates that rejection gives them
the same information.

Might as well let a user logging in that the username is incorrect to make the
legit use case, i.e. user has a typo and/or misremembers their username, more
pleasant.

I usually suggest clearing the username field on failed logins as well. That
way if there is a typo, the user doesn't try it again thinking only the
password is wrong.

------
GlitchMr
I have an argument for "username or password is incorrect" messages: it's
possible that the password is correct, username exists but isn't the intended
one. Then "password is incorrect" message would be lying, as the issue is
actually with a username.

~~~
ajuc
You mean you log onto John with password 12345 and the website says "Some
other user uses this password, but not John"?

Seems wrong, somehow.

~~~
gregoriol
If you, as a developer, are technically able to check that the password is
used by another user, you have failed pretty big at best practices.

~~~
mnarayan01
Doing it every time a user login failed is probably infeasible if you have
even a moderate number of users, but you can presumably do it on an ad hoc
basis unless you have a _ton_ of users. Or am I missing something?

~~~
interfixus
Yes you are. If you have done your security right, users' passwords are not
stored in a form that lets you determine whether one is equal to another.

~~~
alangpierce
It's a little different from determining if one salted hashed password is the
same as another salted hashed password. Whether it's account signup ("the
password is already in use") or login ("you typed in someone else's
password"), you have the plaintext of the password, and can just loop through
the user table and attempt a login for every user with that password. It's
slow when you have a lot of users, as mnarayan01 mentioned, but certainly
reasonable as an ad-hoc thing.

(Not that any of this is good practice.)

~~~
gregoriol
If you are able to do that, then I insist: you probably have failed at best
practices.

Most likely on this part: a good password hashing (ie. security hashing)
should be fast so that you can log-in but slow enough to prevent brute force
(ie. what you are implying). Hashings like md5/shaX don't have that: you can
compute of lot them very quickly, which is their purpose. Bcrypt/Argon2/...
will have a cost/time that will allow only a few computation per second, which
is their purpose.

So if you did best practices well, and try to loop through your users
database, (I assume you have more than a few hundreds users) it might take
some time, some long time. Anyway, you'll then fail at another best practice
because the initial user trying to log in will get bored and be gone somewhere
else ;-)

------
cdancette
Signup and login should behave the same, and provide no information wether the
email is registered or not. And username should be treated as public.

So for login: always say "email or password is incorrect".

And for register: as he said, always say "we sent you an email to verify your
email".

~~~
bo1024
Why? I don't see why it's important to hide existence of a user unless you're
allowing people to try multiple logins per second on your site. (I'm not an
expert so I am sincerely asking to help me understand.)

~~~
jdietrich
Disclosing the existence of a user increases the success rate of certain
attacks.

Say I've got a leaked password database for foo.com and know that the user
bob@gmail.com uses the password "tomato1". If I try using his credentials to
log into bar.com and get the message "username or password is incorrect", I'm
just going to try the next user on the list. If I get the message "incorrect
password", it makes sense for me to try "tomato2", "tomato3" etc. If I know
that your password policy requires eight characters and a capital letter, I'm
going to try "Tomato11". This is obviously trivial to automate.

You can't protect your users against credential-stuffing attacks if they use
the same password everywhere, but you can offer them a small layer of
protection if they use the same password with minor variations.

As others have pointed out, mere disclosure of the existence of an account
could be a serious privacy breach in itself.

~~~
mnarayan01
Any evidence of this being used in the wild, particularly where the attack is
only trying password variants if the initial failure indicated the user
exists? Not disagreeing with the point, just would be interesting if anyone's
seen such an attack.

------
u801e
Not quite on topic, but it would be nice if more websites would offer the
option of using client side TLS certificate "login" with or without an
additional prompt for a username and password.

It would be next to impossible for an attacker to bypass that. For example,
even if the attacker provided the correct credentials, they most likely would
not have the associated client-side TLS certificate private key. Then the
server could just reject the log on attempt outright (since the certificate
wasn't provided or verified).

~~~
mdahlstrand
Sounds like a great solution - would browsers need to support it? Do you have
any resources on implementing it?

~~~
alephnil
Browsers has supported it since the late nineties. The problem are on the
practical side. If you ever log in from more than one machine, all must have
your private key, and the mechanism for synchronising keys between machines
are not there. You have to manually install your key each place. It has also
been too hard for most people to make and handle public/private key pairs.
Also, if you don't have the private key with you, there is no way you can log
in to the site. All of these problem and many other usability problems would
have to be solved for client side certificates to be a success.

~~~
u801e
> If you ever log in from more than one machine, all must have your private
> key, and the mechanism for synchronising keys between machines are not
> there.

I don't think that's good practice. What's better is to have a separate
key/certificate per device that's used to access a service. That way, even if
one machine is compromised (or stolen), then the user can still use other
devices to log in. Also, the service provider can disable certificate log in
on a per device rather than a per account basis.

> Also, if you don't have the private key with you, there is no way you can
> log in to the site.

That's not necessarily true. Some HTTP server software (e.g., nginx) do have
the option of requesting/asking for a TLS client certificate rather than
requiring one. If one is not provided, then it's still possible to connect and
log in. Server side policy can be much more strict in terms of locking the
account in case of incorrect credentials or restricting access to certain
account features if the client certificate wasn't provided.

------
axman6
Even if this doesn’t increase security, you should still do it in the hope the
user will check the username they’ve just typed as well as retyping the
password.

~~~
basdp
Why? Why not just tell the user what is actually wrong?

~~~
tome
Because the application doesn't know what is actually wrong. The error message
is actually correct as written. The user entered their username incorrectly or
their password incorrectly, or both. The application doesn’t know which and
shouldn’t guess!

~~~
rodorgas
This is true for existing user with wrong password, but that message would be
wrong if the user doesn't exist. In this case, the error clearly would be the
username, not the combination user+pass.

~~~
icebraining
How can the pass be correct if the username isn't? A password is only correct
in the context of a specific account.

~~~
irishsultan
The password may be correct for the user (who is a person, and has a password
for that service).

Of course the person may have multiple user accounts and he may have given the
"wrong" password for the "right" username account, but he may also have given
the "right" password for the "wrong" username.

------
willvarfar
The article explains how to do it properly at the end:

> To prevent attackers from knowing whether an account exists or not your
> signup must only take an email address and provide no feedback in the UI if
> the sign up succeeded or not. Instead the user would receive an email saying
> they’re signed up.

Is this not also part of the various 'best practices'? (I confess I don't read
too many of them!)

~~~
tuxxy
Typically, yes. This post didn't really offer any new insight to this. Maybe
it's a PSA? Either way, it completely depends on the site's threat model. In
the case of GitHub, it's quite useless because a user can just go to the
targets's profile to see if it exists. Thus, it really isn't in GitHub's
threat model, obviously.

Where it gets really interesting is when you perform user enumeration attacks
via timing. IE: it takes the server a few milliseconds longer to send a
registration email than to not, or it takes the server longer to try to
validate a password hash than to lookup a nonexistent user.

~~~
aglionby
Is this possible to detect despite external factors (variable latency etc)?

~~~
menacingly
It's black magic to me, but I'm paranoid about timing attacks after seeing a
few examples in the past of what's possible for a clever attacker to guess if
they can gather data from a number of requests.

------
1ba9115454
The solution is relatively simple.

1\. Email and password for login. Don't tell the attacker which is correct.

2\. Email and password for registration. On registration send confirmation
email. If user is already register attacker would need access to their email.
Access to email is game over.

So now an attacker can't see which users are registered with your service and
you've protected your customers privacy.

Extra points if your code is aware of timing attacks.

~~~
tzs
> 2\. Email and password for registration. On registration send confirmation
> email.

This opens up a different problem. It should be:

2\. Email only for tentative registration. On tentative registration, send
confirmation email.

3\. User clicks link in confirmation email, which takes to page for setting
password. (Alternatively, confirmation email includes randomly generated
initial password, user is required to change it on first login). After
password is set, registration changes from tentative to confirmed.

If email and password are both included on the initial registration form, an
attacker can try to sign up people and some fraction of those people will
accidentally click the link in the confirmation email, thereby resulting in
some new accounts where the attacker knows the email and password, and the
email owner does not know the password.

~~~
icebraining
You should definitively set the password after clicking the link. That said,
what would an attacker do with that account?

~~~
tzs
Suppose it were a social media site. Now that attacker has a working account
with someone else's email address, and that email address is considered
verified by the site.

The attacker could then use that account to post threats, harass people, and
so on. If he goes far enough that either law enforcement wants to come after
him or someone wants to sue him and the site is served with a warrant to
reveal information about the poster what they are going to cough up is the
verified email address of the account holder.

That will be followed to the email provider, and from there to the email
address holder. The email holder's claims that he never made the social media
account are going to sound unconvincing--he clicked the confirm link to make
the account!

Remember, a civil suit only requires a preponderance of the evidence, not
proof beyond a reasonable doubt. That verified email might be enough to reach
that standard.

In a criminal case it would not be enough...but if the matter was serious
enough it might be enough to justify a warrant to search the email address
owner's place and computer. At the very least that would be very annoying, and
at the worst it could uncover things that the email holder does not want
brought to law enforcement attention.

~~~
icebraining
And all of this activity on the site happens without the site ever sending a
single other email besides the account verification, that would tip-off the
victim?

Color me unconvinced.

------
davrosthedalek
The title is "bullshit". The real problem is that they leak the information
they try not to leak anyway, on a different form. This is a common, but not
universal, problem.

It's not OK to leak information, even if that information is maybe leaked
somewhere else already.

~~~
zimbatm
In the GitHub case the handles are public information. Anyone can go to
[https://github.com/<handle>](https://github.com/<handle>) to verify if it
exists. So they trade off usability of a clear error message for no gain at
all.

~~~
tantanel
This is true for the username but it's possible to make your email address
private on GitHub in which case the message that your email is taken can still
be considered an information leak.

~~~
jwilk
You can check if an e-mail is associated with a GitHub account easily. You
forge a commit with this email as author email, push it to a foo/bar repo,
then look at
[https://github.com/foo/bar/commits/master](https://github.com/foo/bar/commits/master)
.

------
j_s
Ask HN: Why does Amazon allow multiple accounts with the same email address?
(2014) |
[https://news.ycombinator.com/item?id=7075372](https://news.ycombinator.com/item?id=7075372)

~~~
nhumrich
Interesting. Just reading this now, but it makes me wonder, what happens if
you set two accounts to the same password?

~~~
falsedan
> _you can create two accounts with the same e-mail address, but you will get
> into trouble if you try and give them the same password. I 'm not sure what
> happens, so try it and see._

------
rafaelbarbosa
It's still good advice for software where there is no public signup, such as
SaaS where accounts are created by administrators.

------
jkire
Isn't the other reason so that adversaries can't tell if a particular
username/email has signed up? This is not so useful for something like github,
sure, but certainly is useful for the more embarrassing sites where users have
an expectation the site won't leak their membership.

So in some ways I've always thought of this as a privacy concern rather than a
security one?

Edit: I guess I'm thinking purely of emails where you don't get availability
checkers during sign up.

~~~
pgeorgi
As the post demonstrates, you simply go to the login form to validate the
presence of accounts.

Few sites remember to anonymize that, which might be the real PSA: in such a
case, if you require an email confirmation anyway, just send the "recover
password" email internally, but let it look like the regular sign-up flow.

If you don't requite email confirmation, anonymous membership isn't possible
(just try to sign up with that account, what is the site supposed to do that
looks legit without giving away information?)

------
alexozer
If you're just trying to find a set of accounts with a weak password, isn't it
much more viable to use the sign-in page that shows "invalid password" instead
of "invalid username or password" rather than dealing with captchas on the
signup page? Assuming you can't just find usernames as public profiles like on
GitHub.

------
JansjoFromIkea
There's definitely a trend away from this to some degree lately, I feel. It's
probably more influenced by Google not doing it with their accounts (enter
username -> forwarded to password page with your avatar) more than anything
else, mind.

------
styfle
I asked this same question[0] on StackExchange earlier this year. It has been
asked many times and it really comes down to considering a username a secret
or not.

In B2B applications where there is no registration form, then the username is
probably a secret. In B2C applications where anyone can register, then the
username likely isn't a secret. Many of those applications have the concept of
"mentions" by username so clearly the username is not considered a secret in
that case.

[0]:
[https://security.stackexchange.com/q/158075/11536](https://security.stackexchange.com/q/158075/11536)

------
rawnlq
Try searching for your username on
[https://namechk.com/](https://namechk.com/)
[https://www.namecheckr.com/](https://www.namecheckr.com/)
[http://checkusernames.com/](http://checkusernames.com/) or
[https://pipl.com](https://pipl.com). I am sure these name checkers can't be
built if they have to spam the sign up forms just to check availability (at
least not for free if they have to pay for manual recaptchas).

The privacy is worth it.

------
rmetzler
This is actually a feature for users who have almost the same username and
mistype this instead the password. E.g. this could probably happen through an
unfamilar kayboard layout.

I understand that a lot of people think this is a security feature, but once
upon a time it was the lazy programmers answer when "SELECT * FROM users WHERE
username=? AND password=?" didn't return a result.

With proper salts for hashed passwords you now have to find the username, use
the salt to hash the password and compare this. If your database allows to
hash passwords with a dedicated function it's still the easiest to say
username OR password must be wrong.

------
oliwarner
Stripe does it wrong, so it's wrong everywhere? Nah. _That 's_ bullshit.

For emails, you can very easily fake a second signup with the same email and
ping out an enhanced verification email "Somebody just tried to register with
this address but you already have an account".

Building the username into that flow is harder. That's why I preference not
having separate usernames but some people would argue this is itself a bad
thing (removing a factor or somesuch).

Either which way, _Stripe 's approach is broken_. That doesn't make the whole
idea nonsense.

------
kuceram
Here is a super useful article about how you should build login
[https://blog.codinghorror.com/the-god-
login/](https://blog.codinghorror.com/the-god-login/) (if you don't want to
rely on professionals from Auth0 or Okta :-). In the article, there is a very
good statement "being user friendly is way more important than being secure"
and this is exactly this case also...

------
sika_grr
> Even if reCAPTCHA was perfect, a hacker could manually validate their
> usernames of interest by trying to sign up, then automate an attack on the
> sign in page.

Why is imperfect reCAPTCHA worthless? Do sign up pages even allow brute
forcing of usernames (once validated)?

Is he suggesting to fix sign up pages, or to allow brute forcing usernames on
login?

His writing style is dramatic, but the arguments are very weak.

------
kyberias
I like the dramatic style this opinion is written.

~~~
maephisto
I could totally feel this blog post, not just read it.

~~~
travisjeffery
Haha, that's cool with me.

------
exabrial
My other favorite security theater advice is locking an account after x number
of failures. How could this used for anything but DOS?

Depending on the service that's being protected, rate-limiting to 5 minutes
between attempts, alerting the owner, and assigning them a temporary username
seems more reasonable countermeasures to me.

------
z3t4
After reading this I went straight to change the login system I'm currently
working on ... And discover that I would need to add some extra code paths /
conditionals ... So for me it's not "best practice", it's more todo with
laziness and not wanting to add complexity to critical functions.

------
skywhopper
This is a pointless argument because I doubt Github or anyone who uses this
message seriously considers it to be a security measure. Github's usernames
are absolutely public. But they also have so many users that I suspect the
wrong username is typed all the time. So yes, sometimes maybe the username is
wrong.

------
zanedb
I have felt this same way for so long and I'm really glad someone finally
wrote about it.

------
dreamdu5t
What’s the point of having passwords at all? If there’s a password reset
mechanism they provide no additional security. Just send a one time login
token to the email.

Having a password just increases the odds of a hack by the user accidentally
exposing it.

~~~
stordoff
At the expense of convenience - I often need to access accounts on devices
where I don't have access to my emails (e.g. if I'm using a semi-trusted PC
[family devices etc.], I might login to Amazon, because anything there can be
undone, but I wouldn't login to an email account [and if I haven't memorised
my email password because it's in a password manager, I might not even be able
to]).

------
hbk1966
Also if you are doing the username/password is incorrect you should also add
an artificial delay if it's the username is wrong. Because you can tell which
one is wrong my seeing how long it takes the server to respond.

------
samnwa
I suggest we just randomly say your username or password is incorrect.

"Your username is incorrect" "Your password is incorrect" "You hit the wammy.
Try logging in again."

That way, you never know what's going on at all.

------
chicob
In the article: "You gain no security, yet your customers lose clarity."

Oh boohoo. Like it's not on the customers side to know which email it is and
which password.

And as many have said, one does gain privacy.

------
godzilla82
So, as per the author, sites should first check if the user exists and then
check the password? Why? What if the username belongs to someone else?

------
27182818284
Lately I've seen the catch-all "We could not verify the credentials you
entered" and it has grown on me a lot.

------
scotty79
... also, you can often do "Forgot my password" and if you give unregistered
email it will tell you that.

------
vatotemking
Doesnt “username or password is incorrect” falls into the Security through
obscurity category?

------
observation
Good point. I'm embarrassed it didn't occur to me before.

