2

I'm doing some research on user account guessing, and wanted to ask a question about some "bad practices".

My thought is generally this is a trade-off between great user functionality/UX and security. For example, I could create a user webservice that checks if an e-mail exists, and when a user is attempting to register, I can (as a convenience) let them know that this account already exists (instead of having to go through the entire process only to find out at the end the account is taken).

In addition for a login form, telling the user 'this username/password is invalid' instead of 'that username does not exist' will help reduce the chances of an attack.

At the end of the day (for registration), my thought was the aforementioned webservice is a bad idea, but there needs to be some way to ensure the user knows that name is taken/available.

What are some techniques people do to secure this? I thought that rate-limiting service requests from a server perspective is a good idea. Is this common? For example I have some sort of means of blasting away at that webservice using a dictionary attack. After enough time, I could have a whole list of e-mail addresses that are valid and now I only need to guess passwords instead of both. But if the service is limited such that after N requests, the response slows down, or asks for a CAPTCHA, it would be harder to pull this off (now I need to use unique IP addresses, etc).

I wanted to see if my thinking was right here or if anyone could add on to this.

By the way, I noticed Microsoft does not do this! When you go to live.com, and you type in some made-up username, it tells you that username does not exist. When you try a valid username but bad password, it tells you that password is wrong! Isn't this a bad practice? What are some reasons they allow this? Because it's a popular service and getting a live e-mail address is pretty easy? Or maybe that coupled with lots of server security?

No Time
  • 105
  • 9

2 Answers2

1

Most of your assumptions are correct.
The general idea (as far as the user interface is concerned) is:

  • give the attacker as little information as possible
  • slow down the attacker

If people need to register you cannot avoid the error message 'This user already exists'.

If registered users need to login the generally recommended precautions are indeed:

  • Only report on an invalid combination of id/password
  • Limit the number of login attempts, then block the account. If you don't want to do that:
  • Introduce a longer delay for every attempt. Alternatively: delay every attempt. For a user logging in, 2 seconds extra is no big deal. For an attacker, it is.

You should of course also use the delay for the registration phase.

Not everyone follows recommendations ;-)

1

Rate limiting is probably the only practical way to mitigate these attacks for most public-facing applications. And you're correct in that it's a security/UX tradeoff.

Given the login form example alone, "your username or password is invalid" is a more secure (exposes less information) way to present info, but most public services have other endpoints to check for usernames anyway.

The attacker can, for example:

  • check for a "user profile url" if implemented in the app (eg. /users/profile/NAME)
  • or hit the "create a new account" endpoint and get "username/email exists" info from there.
  • or create a new account and hit a (for example) "send a message to user NAME" and get info from that response.
  • etc, etc

If you add rate limiting then these attacks will take a lot longer (to the point of being impractical — depending on your user base size and rate limiting details), but in theory it's still almost always possible.


It's possible to leak zero information about accounts, but that will make the experience for actual users much more confusing.

Imagine an existing user tries to create a new account — you have to accept all the info, show an "Account created" page, detect it's a duplicate, and email the user that "you tried to create an account, but already had one".

Joel L
  • 1,427
  • 11
  • 12
  • Your zero information example is a little strange. If the existing user is emailed that someone tried to create an account in his/her name, that might confuse and alarm the user. Most site operators don't give away such information. A question would be, why that is. The other possibility: if the newly created user is emailed (assuming the username is the unique part and a different email was selected), then the attacker would have found valid username. This is of course mitigated, because nearly every site uses email addresses as primary keys. – Artjom B. Jul 31 '14 at 19:00
  • @ArtjomB — in this scenario the point is that the attacker would not know if the email address he tried was previously used for an account. He'd simply get the "Please check your inbox to proceed creating your account" message. And if the user himself accidentally tried to create an account, they'd get an email saying "Welcome back, you already had an account". – Joel L Jul 31 '14 at 19:06