Friday 4 April 2014

Removing usernames and enforcing unique passwords

I often have "ideas" that, in the haystack of my mind, are usually straws rather than that elusive needle. One recent one was whether the username is necessary to login to a website.  Usually the Internet is excellent at helping identifying straws, and this idea is no exception, see http://blog.codinghorror.com/why-do-login-dialogs-have-a-user-field/.  But let's follow through on the idea and see where it takes us.

So the basic idea is that when a user wants to authenticate to a website, all they do is provide their password and the website will use that information to identify them.

The draw of removing usernames for me is really an efficiency one, as it's not immediately clear that usernames are required to authenticate to a website.

The obvious problem though is if someone tries to register with the same password as an existing user.  Since we can't have 2 users with the same password (more on unique passwords later), we must reject the registration and reveal that the chosen password is a valid credential for another user.  We can overcome this problem by forcing the existing user with that password to change their password (using (an assumed pre-existing) out-of-band password reset mechanism e.g. email).  Which highlights one benefit of authenticating with the password only, it creates an incentive for the user to choose a strong password (as otherwise they will continually have to change their password when new users attempt to register with the same password).

From the website's perspective there is a problem though, how do you identify the user?  If passwords are being stored using a salted password-hashing algorithm, then it would be too inefficient for the website to, for each row in the password hash DB table, fetch the salt for that row, then generate the password hash (using the password of the user trying to authenticate), and the compare it against the stored password hash in that row.  That approach simply does not scale.  We certainly don't want to use a password hash without a salt or with a fixed salt (as this makes dictionary attacks on the password hash DB table much quicker in the event the table is exposed).

One option is to encrypt the password and use that as the salt for the password hash.  To verify a login attempt the website would encrypt the password to create the salt, calculate the password hash (using the salt) and compare with the list of stored password hashes (potentially sorted for efficient searching).  It's important to point out this encrypted password, which we are using as the salt, is not stored, but calculated during the login attempt.

If the password hash store was ever compromised (and we always assume it will be) then it will be impossible to brute-force the passwords without the encryption key as well (as the salt will not be known and not be practical to guess).  Thus the security of this approach relies on protecting the encryption key.  The key should not be stored in the DB, as the likely extraction method of the password hash DB table is SQL Injection, meaning if the key was in the DB it too could be extracted.  The key should be stored somewhere the DB cannot access (the goal is to require the attacker to find a separate exploit to obtain the key).  It could be stored in configuration files, but the best option would be an HSM, with encryption done on-board.  At the stage an attacker has code executing talking to the HSM, it's game over anyway.  If the encryption key was obtained by an attacker then they could more efficiently (than attacking traditional salted passwords hashes) perform a dictionary attack on the password hash DB table.

We can make another optimisation for security as well.  We should keep track of the passwords that more than one user has chosen in the past i.e. password collisions discovered during user registration.  After all, we don't want to force a user to change their weak password, only for that password to become available for use again!  This way we will avoid the re-use of weak passwords e.g. 123456.  Now imagine we had a list of passwords that we know more than one person had thought of.  Now imagine we publicly shared that list (so other websites could avoid letting users choose those passwords as well).

So let's imagine we now have an application that doesn't require usernames for authentication and all users have unique passwords.  What are the threats?  Well a distributed dictionary attack against our application is a problem because every password guess is a possible match for every user.  Annoyingly the more users we have the better the chances of the guess being right.  Additionally, limiting the number of guesses is more difficult since authentication attempts are not user specific.  This makes clear the benefit of having usernames; they make online authentication attacks much harder.

So my conclusion was that although usernames might not be strictly necessary, they do offer significant security benefits.  From a user perspective as well there is minimal burden in using usernames as browsers (or other user agents) often remember the username for convenience.

But what about the benefits of unique passwords!  What about the incentive we gained when users were forced to choose strong passwords?  Well what if we keep usernames AND still forced passwords to be unique?  Could this be the best of both worlds?  Might I have just pricked my finger on a needle?

The 'sticking point' for me is the user acceptability of forcing unique passwords.  It may drive the uptake of password managers or strong passwords, or it might annoy the hell out of people.  Perhaps for higher security situations it could be justified.

No comments:

Post a Comment