80

It is really common (and I would say it is some kind of security basic) to not show on the login page if the username or the password was wrong when a user tries to log in. One should show a generic message instead, like "Password or username are wrong".

The reason is not to show potential attackers which usernames are already taken, so it'll be harder to 'hack' an existing account.

Sounded reasonable for me, but then something different came on my mind.

When you register your account, you type in your username. And when it is already taken, you get an error message - which is not generic!

So basically, an attacker could just grab 'correct' user names from the register page, or am I wrong?

So what is the point about generic messages than? Non-generic messages would lead to a much better UX.

Anders
  • 65,052
  • 24
  • 180
  • 218
Mirco
  • 903
  • 1
  • 8
  • 8
  • 4
    There are sites like Yahoo mail for example, where enter the right username and incorrect password gives the generic message. On entering "Incorrect Username" it gives a message "This username is not taken ..." so much for security. I think this is a relic from old days and does not have place in today's scheme of things. – Dheer Jul 08 '14 at 06:47
  • Additionally, when you mistype your password on the Win7 lockscreen (where the username is preselected by default) you still get the generic message... – Nicktar Jul 09 '14 at 11:54
  • 4
    I prefer the "Forgot password" function, which also tells me if the username is valid or not in many cases. The link is usually near the password field, no need to go the "Register" detour. – basic6 Jul 09 '14 at 14:57

10 Answers10

67

No, you are correct that at some point during efforts to prevent attackers from determining valid user identities you will either have to lie to them or provide exceptionally vague error messages.

Your app could tell a user that "the requested username is unavailable" and not be specific as to whether it was already in use or just didn't meet your other username requirements (length, character usage, reserved words, etc.). Of course, if these details are public then an attacker could work out that their guess failed due to the account being in use and not due to invalid format.

Then you also have your password reset system. Do you accept any username/email address and say a message was sent even if that account wasn't in your database? What about account lockout (if you're using it)? Do you just tell the user that their credentials were invalid even if if they weren't but instead their account was locked out, hoping they contact customer support who can identify the problem?

It is beneficial to increase the difficulty for attackers to gather valid usernames, but it typically is at a cost of frustrating users. Most of the lower security sites I've seen do use separate messages identifying whether the username or password is wrong just because they prefer to err on the side of keeping users happy. You'll have to determine if your security requirements dictate prioritizing them over the user experience.

PwdRsch
  • 8,361
  • 1
  • 28
  • 35
  • 7
    If the site lets you *choose* a username (without the same advice in place as when choosing passwords) then it's kind of a joke to then keep usernames secret. OK, some users will benefit from the secrecy since they'll choose hard-to-guess usernames, but user "dave" won't get that benefit regardless of what measures you then take to try to keep it secret ;-) So it can hardly be essential. – Steve Jessop Jul 10 '14 at 09:13
  • 2
    +1 for `... determine if your security requirements dictate prioritizing them over the user experience` – karancan Jul 14 '14 at 20:10
  • 1
    Well, you *could* combine password-reset and account-creation: Any account which could be created, does sort-of exist, it's just that noone knows the password. – Deduplicator Oct 26 '15 at 15:42
35

You're making the assumption that the system actually knows which field was entered incorrectly. There are several reasons this is not necessarily true.

One possibility is that it's a side effect of implementation. A simplistic method of looking up logins in a database might look something like (using :n for parameters supplied by the user):

SELECT 1
  FROM users
 WHERE username=:1 AND
       password=HASHING_FUNCTION(CONCAT(:2, salt))

If you get an empty result, you know the login should fail, but you don't know why unless you do something more complicated or make another query. So sometimes it may just be laziness or a desire to go easy on the database, rather than a conscious security decision.

But even if the implementation can distinguish between an nonexistent user and incorrect credentials, you still have the situation where a user enters their password correctly, but the wrong username, and that happens to be a user that exists (with a different password). Then, if the user got a message saying their password was incorrect, that would be wrong. So unless the specified username doesn't exist, the system can't actually know if it was the username or password that was wrong.

l0b0
  • 3,011
  • 21
  • 29
nobody
  • 359
  • 2
  • 3
  • 18
    No security-conscious system should use this type of authentication because in addition to hashing, you need to have a salt. And ideally, a per-row salt. So look up by name, grab salt and hash, compare. – MaxSem Jul 08 '14 at 06:10
  • 3
    And, I would doubt a proper HASHING_FUNCTION is implemented by most DBMSs, and I would also suspect this might be susceptible to timing attacks. I wouldn’t do that. – Mormegil Jul 08 '14 at 13:00
  • 5
    Especially the second point is excellent! If the user has a typo in his username, but randomly matches another username, the corret Message would be "Wrong Username" because for the user it is a wrong username, even if the system found it in the DB, so the generic one is always better! @Mormegil I think the code is valid, HASHING-FUNCTION should of course be a cryptographically safe hashing function. But Timing is not an issue, except you know if a username is probably not in the DB because of fast index scan. But as mentioned this is probably irrelevant for most modern applications – Falco Jul 08 '14 at 13:58
  • 1
    @Falco Well, _either_ HASHING-FUNCTION is something like SHA-256 (which might be implemented in the DBMS), which is a fast hash, _not suitable_ for password hashing, _or_ it is something like PBKDF or BCRYPT (which is probably not provided by any current DBMS) and a timing attack would be able to trivially distinguish whether a username was found (and the password is wrong), or no username was found. Simply said, I have no idea why anyone would want to implement it that way. (The second point is valid, though.) – Mormegil Jul 08 '14 at 17:45
  • 1
    @Mormegil PostgreSQL provides bcrypt. It might be subject to timing attack depending on how you craft the query. – jjanes Jul 10 '14 at 05:52
  • You could do it this way if your per-row salt was generated from the user name, say by feeding it into HMAC with a secret key. Obviously to avoid timing attacks you need to make sure the password hashing is done whether the username exists or not, but that's trivial. – armb Jul 10 '14 at 09:24
13

In general, it is harder to brute force a registration page than it is to brute force a log in page, so we benefit from this additional cost. But, in concept, you are correct. There are other ways to enumerate usernames than log in page messages.

It is simply 'Good Practice'(TM) to keep log in failure messages generic in order to make it harder for attackers to glean good accounts from bad. Using a brute force tool, it is trivial to try random names, and then when the error message changes, to start brute forcing that username.

But, as always, you need to balance usability with threat reduction.

schroeder
  • 125,553
  • 55
  • 289
  • 326
  • 5
    Yes, this. Registration page usually includes some form of CAPTCHA. – domen Jul 08 '14 at 11:42
  • 6
    So long as the CAPTCHA or other challenge/puzzle comes _before_ the user is told that the name is already taken. There should also be a reasonable wait period between tries, but not so long as to discourage a real person trying to set up a real account. – Phil Perry Jul 09 '14 at 17:02
6

Not all systems have account registration. For instance, your operating system login does not. Websites do stop accepting new members from time to time.

It's a question of separation of concerns: should the login dialog query the system configuration and customize its behavior based on whether the system is configured to accept applications for new accounts or not? Then the login dialog is coupled to information that is not really relevant to its job.

It seems easier to just implement the vague error message in all cases (assuming that the UI software even knows whether it was the password that is bad, or the account nonexistent: what if it gets a generic authentication error from some lower level API?)

And, also: the new user application UI can implement a long-ish fake delay like "searching user base ... [10 seconds] ... oops, user name is already taken!" If that is implemented, it means means that probing the space of user ID's through this mechanism is severely rate-limited. Since applying for a new account is a rare, one-time operation, users will suffer the delay, whereas they would grow aggravated by a ten second delay in the regular login dialog.

Kaz
  • 2,293
  • 16
  • 17
5

It depends on what the user name is. There are three main approaches for user names:

  • User selected name
  • Email address
  • Assigned user name - usually a string of digits

You are correct that for user selected names, an attacker can use the registration process to infer what names are in use, so there's limited benefit to the login returning a generic message.

However, for the other two cases, it is much more important that the login screen returns a generic error message. Consider a recruitment site, it could be embarrassing for joe.bloggs@abc.com to have his boss discover there is an account on a recruitment site. And assigned user names are most commonly used on high-security sites like online banking.

paj28
  • 32,906
  • 8
  • 93
  • 130
  • For email addresses, you are assuming that when you go to register a new account and provide an existing email address, it doesn't immediately give you an error saying "email address already in use"; otherwise, there's not much benefit from avoiding revealing this on the login screen, if it is revealed on the registration screen. One way to avoid this would be to have the registration screen require a CAPTCHA before telling you whether the email address you provided has already been taken or not. – D.W. Jul 09 '14 at 22:07
  • 2
    @D.W. - sure, or you can do this without a captcha by first sending a confirmation code to the email address, and only once confirmed informing the user if the address is already taken. – paj28 Jul 10 '14 at 07:43
4

Yes, you are correct. Anywhere on your site where it can be confirmed that a username exists or not can lead to username enumeration.

However, this problem can be solved if it important to your system. Within some systems, username enumeration cannot be avoided as it is inherent to the nature of the application. One example is a web mail service - here email addresses are deemed potentially public. Preventing users from knowing other usernames is difficult without requiring the users to log in with a different identifier than their hosted email address and can lead to confusion and difficulty in recovering lost credentials.

However, with most other systems this can be fixed by having the user's email address as their login username. You would solve the problem by having the forgotten password and the sign up form as effectively the same page. For sign up, this would be a multi-step form and the first step simply asks for the username (email) that the user wishes to use with your system. For account recovery, this would be the same form but the title would say something along the lines of Please enter your email address to generate a password recovery email.

In both cases, the form will send the user an email. If they are already signed up then the contents of this email contain a password reset link. If they are not signed up then the contents of this email contain a link to the next stage of the sign-up process. This will prevent usernames on your system being enumerated so an attacker will not know which accounts to target.

Of course this implies that you are willing to allow passwords to be reset by email which may be unacceptable for some applications such as banking applications. However as these sort of accounts usually have additional security checks, they usually have bank assigned usernames rather than allowing people to pick their own.

SilverlightFox
  • 33,698
  • 6
  • 69
  • 185
2

The common argument for vague messages seems to be to prevent attackers from guessing valid usernames. There's actually a simple solution that doesn't severely impact legitimate users, and should be in place anyway: restrict the maximum number of failed attempts in a period of time.

By restricting attempts, you prevent all brute-force attacks. Say you only allow 5 attempts per 15 minutes (common on forums) - that makes a username-guessing attack all but useless. It also prevents password brute-forcing (as uselessly slow as that would be on a remote site anyway).

Of course, an attacker might already have a database of usernames, and merely wishes to check if they exist on your site. And you'll need to consider the security implications of that, but generally they either already have the password (making this discussion moot) or they won't (so restricted attempts prevents guessing anyway).

Bob
  • 1,198
  • 10
  • 14
  • I would think on something like a forum, it would be much faster to simply crawl existing public posts to discover usernames rather than try to brute force them. Some forum softwares even include a page which enumerates the usernames for you! – Brian S Jul 09 '14 at 19:26
0

To avoid username enumeration on the user registration page, an application can allocate username automatically based on the user's email address rather asking the user to choose one of there choice.

This way it can be prevented username enumeration or registration page.

Also, we should take forgot password functionality into consideration, sometime this should also reveal valid user details.

0

A smart website would have a captcha on their registration page to prevent this sort of thing.

But you know how 99% of websites are. They will ruin their UX with a generic error message, even though it doesn't give them any extra security. Personally, I don't bother with generic error messages since there are plenty of other restrictions in place for my logins (captchas, limited login attempts), plus logins are like the #1 reason people will ditch a website.

If you do choose to display a generic error message, then good god, go all the way with it. Make sure there are no loose ends anywhere. You can reinforce a wall with 10 inch thick steel, but that won't help if there's an unlocked door in it.

  • 2
    Recaptcha's are easily broken by a recaptcha solver. These sites often charge a low fee and have about 70% accuracy rate. Captchas (no reCaptcha) are even easier for a computer. Sometimes the computer is better at it than a human so it just provides an annoyance for your users. – Travis Pessetto Jul 07 '14 at 21:22
  • Making a decision on what works for your environment is fine, but you need to explain why you made that decision so that others understand its context. Your mitigating methods do nothing to address the concern of enumerating user accounts. Did you feel that enumeration was not a risk for your environment? Please provide more than hand-wavy dismissive statements. – schroeder Jul 07 '14 at 21:24
  • See http://deathbycaptcha.com and http://scraping.pro/decaptcher-review/. I do agree with limited login attempts. – Travis Pessetto Jul 07 '14 at 21:31
0

I am trying to put my attacker hat on and I see 2 cases:

  1. Your site has a registration page (such as gmail or stackoverflow). I could use the registration page to figure out the user name of an existing user by brute force. Or I could just create a new user. My new gmail or stackoverflow user will probably have about the same rights as the one I would have brute forced.

  2. Your site does not have a registration page. Your point is void.

emory
  • 1,570
  • 11
  • 14
  • This answer is nonsensical. How would creating a new user do anything? Why did you raise a 'straw man' with point #2? – schroeder Jul 08 '14 at 02:43
  • @schroeder for example gmail. You could use the 'register' page to determine the identity of an existing random gmail user and then try to brute force the password. But will the random gmail user account likely have greater privileges than the ones you can create? – emory Jul 08 '14 at 11:45
  • 1
    Attackers tend to brute force accounts in order to get the data of THAT account, not to simply gain access to a system. You are raising points that are designed to be dismissed. – schroeder Jul 08 '14 at 14:10
  • @schroeder if I am attacking a particular account then the fact that the system has a registration page or a non-generic error message is of what use? For example, the person who hacked Palin's email knew her username before hand. – emory Jul 08 '14 at 21:11
  • If you have a particular target in mind before the attack, sure, but that's also not in the scope of the question. As an attacker I want to know what ANY account will have available. Not as having access to the system, but to mine whatever is possible from their account: PII, account info, re-used passwords, etc. None of my points are new or unusual. I'm getting the feeling that you just like to be dismissive. – schroeder Jul 08 '14 at 21:17