Home Home

Bad, bad passwords

Arseni Mourzenko
Founder and lead developer, specializing in developer productivity and code quality
130
articles
June 18, 2015

Passwords are an aberration. In a ideal world, we wouldn't have passwords, but only keys.

The concept of a password as a security measure is flawed, and leads to multiple issues. Among others:

  1. When the password is sent by the client to the server, any man in the middle can read it and use it.

  2. Remembering passwords is not something humans are good at. This leads to security through Post-its and short passwords.

  3. Generating and handling good, secure passwords is difficult. It requires cryptographically-secure pseudo-random number generators, and specific software which can store them semi-securely. Most password managers are extremely poorly made by people who have no expertise whatsoever in security or user experience. This, in turn, means that few persons use such software, and the ones who use it may have a wrong sense of security.

  4. Validation of passwords is not an easy task either, like shown by thousands and thousands of compromised websites, including very popular ones. Although many frameworks made this task easier by hiding hashing and salting logic under an interface with two methods: one for storing a password, another one for validating it, there are still to many programmers who believe that storing an MD5 of the password is perfectly fine.

  5. Managing passwords for a company is also quite complicated, which leads to passwords reuse (how many times, working as a freelancer, did I have a root password to the production servers of my customers?!) and wrong lifetime of passwords (either regular renewal, which is a wrong practice, or no expiration for accounts which shouldn't be used any longer.)

This makes passwords a flawed feature, and a dangerous one. If there is one advice I can give to someone, it would be this one:

Don't use passwords. Use keys instead.

Keys don't have many of the flaws passwords have:

  1. Since they are used to solve a challenge, man in the middle attack is practically impossible.

  2. One don't need to remember a private key (and probably couldn't).

  3. Keys are generated by an application anyway, without the alternative for human-based generation. Of course, some applications are good at what they do, some are not.

  4. Validation of keys is straightforward. There is not much a programmer can do as mistake here.

  5. If keys have an affinity with a machine or a user, reuse becomes impossible. Also, few network administrators have the stupidity to renew keys every 30 days. Expiration, however, remains an issue.

Of course, there are cases where we can't rely on private/public key pairs, and so we must fallback to passwords, which leads to the discussion about the password policies, what is secure and what isn't.

In my entire life, I've probably seen a thousand of different systems which require passwords. I wouldn't be surprised if less than a dozen among them had a policy which encourages secure passwords. Most are completely stupid. They encourage security by Post-its, or simply force to use poor, easy to hack but difficult to remember passwords.

Length

The length is a crucial aspect of a password. “1234” is not a secure password, but neither is “T30K”. For any system which should have at least some security, minimum length policy should be enforced.

Many systems enforce the opposite: the maximum length. While this is not inherently wrong, the maximum value they set is. A value of 16 characters seems to be particularly popular, and I have no idea why (and why not 15 or 20). I've equally seen limitations to a maximum of 10, 8, or, in one case, 4 characters.

Low maximum limitation has three negative consequences:

  • When dealing with randomly-generated passwords (which are often from 20 to 50 characters long), this limitation is painful to deal with.

  • The limit is usually not consistent across the system. For example, for a long time, Microsoft silently limited (trimmed) my password to 16 characters at some locations, but not on others, which means that when entered in forms where it was not trimmed, I was faced with a error telling that my password is invalid. As a user, I'm not expected to know or care about the trimming.

  • Combining multiple words to form a password is impossible. “correct horse battery staple” is 28 characters long, and won't work with most systems.

While it is understandable that there should be some limitation of the length, the value should be reasonable. A maximum length of 1 000 characters seems a good compromise between security considerations and network bandwidth usage. In practice, I wouldn't blame a programmer who limited the length to 100 characters, but I see no valid reason to set it lower.

Characters

Fifty years ago, there was ASCII. Since 1991, we have Unicode standard, and while its support is still limited with some technologies and languages (such as PHP), it's quite well done in others (such as Python). However, many programmers believe that they allow characters beyond a subset of ASCII to enter the passwords, bad things will immediately start to happen.

This leads some programmers to limit passwords to capital and small Latin letters, digits and a few symbols they are comfortable with. With more than sixty possible symbols to use, this is not that bad in terms of security, but what about user experience?

  1. The randomly generated passwords may not use the same characters as the ones programmers decided to allow.

  2. Users may not be comfortable with those characters; for instance, a Russian user will necessarily be forced to switch to a different keyboard layout just to enter his password.

  3. Users need to read the stupid limitations and to apply them when creating or changing their passwords. The fact that visually identifying which characters are allowed and which are not is not particularly easy makes the situation even worse.

“This isn't a great deal”—a programmer could reply. Well, it is. Impacting user experience should always be a great deal, but sometimes, it is necessary for technical or financial reasons. Here, the worst thing is that there are no technical or financial reasons whatsoever. Even worse, you're wasting money to define a complicated limitation for allowed or denied characters, when you may do it much simpler.

In Unicode, there are three possible problems with passwords.

  1. Control characters are extremely problematic, since different systems will behave differently when handling them. Don't allow those characters for passwords. Never. Notice that this limitation doesn't impact most users: I can hardly imagine a legitimate user entering a control character in a password field in his browser. The only case when there is a negative impact is when the authentication is performed by a machine which actually sends a binary stream of data, and don't care if there are control characters or the zero byte.

  2. Normalization could be another problem, but it's actually very easy to solve. In Unicode, characters can be normalized differently. An accented letter can be written as a single character—that is an accented letter itself, or an accent followed by a letter, or a letter followed by an accent. Visually, there will be no difference for the user. However, the hash of different representations of the same string will be different, which means that your system may end up telling to the user that the password is invalid, while the password he actually entered is perfectly correct for a human.

    The problem is easily solved by applying a specific and consistent normalization before hashing a password. This is purely a technical issue, and most languages and frameworks have enough support to make it easy.

  3. Special Unicode characters like the ones which cannot be displayed on some systems are problematic in user names or other elements which are displayed publicly. When it comes to passwords, they are never displayed, which means that the problem is irrelevant here. Even in a case of password reset procedure, it's the newly generated password which is sent by email, not the old one.

Aside those cases, any other character should be authorized. Why couldn't a Chinese guy write his password in Chinese? Why should a person from Greece switch the keyboard layout to enter a password using symbols she may not even be used to? And especially, why lowering the security of passwords with no technical benefit whatsoever?

Expiration

There is one fundamental rule when it comes to password security:

Passwords should not expire on schedule.

Users shouldn't be forced to change their password every 30 days. Nor every 90 days. Nor every 365 days.

Automatic password expiration sucks. It encourages users to write their passwords on a Post-it, or in a plain text file. It makes users hate their system administrator, and hate the system which forces them to change their passwords. Please, don't force poor security practices just because you can.

There are absolutely no reasons for forcing a password to expire automatically. If you think it is a way to prevent brute force (and if you're really that desperate that this is the only thing you have to prevent brute force), then you should set passwords to expire every two minutes, because often, brute force is as fast as a few minutes. Rare are hackers who will spend a month brute-forcing a password (and seriously, if you are administering a system where somebody can stay unnoticed while brute-forcing an account for a month, consider searching for a job which is better suited for you).

Storage

Storing and validating passwords is a tricky task. It requires a solid understanding of the subject (no, no, computing an MD5 hash of a password is not the right approach!), and requires a large amount of code to be written and thoughtfully tested.

A better approach is to let someone else, someone more experienced than you, manage the passwords. Luckily, with OAuth and OpenID, this approach is not only possible, but also easy to implement.

For practically every application at Pelican Design & Development, the only authentication mechanism is through OAuth 2 with Google as provider. This means a lot of things:

  • I don't have to write and test all the source code related to passwords salting and hashing, to brute force attacks, to password reset procedure, to device-based authentication, etc. Google does that, and I'm pretty sure it does that much better than I could do it.

  • I don't store passwords, not even in a salted and hashed form. This makes my infrastructure less interesting for an attacker.

  • I don't even receive passwords from the users. If an attacker compromises a machine and finds a way to monitor everything which comes in, he still won't get the passwords.

  • I don't pay for sending SMS messages for customers who want additional safety with device-based authentication. Google pays that.

  • Google handles all the cookie stuff, remembering passwords on client side in order to bring better user experience to my customers, in order for them to avoid entering their password too often. All that for free. Thank you, Google.

Delegating passwords validation and management to another entity is essential: not only does it increase security, but it decreases tremendously the money and time wasted handling this part of the application.

More passwords don't increase security

Some companies are forcing users to enter multiple passwords through multiple systems in order to access the internal resources. By asking for more passwords, they hope that they will increase security.

This is a wrong approach, and a harmful one, since it gives a wrong sense of security.

How passwords can be compromised?

  • The system itself can be.
  • The user may have a keylogger installed.
  • The man in the middle can monitor the traffic.
  • Somebody can gain access to the user's machine or office and get the passwords stored by the browser or written on Post-its.

Except the first case, having two passwords instead of one have absolutely no effect. On the other hand, its negative impact on user experience is very important.

Don't force the user to enter multiple passwords to access a resource. If password-based security is not enough (and as I previously explained, it's not), you should use device-based authentication additionally to a password. A common form is to send an SMS to a person after he enters a password, the message containing a short code the user should enter on the website.

Forbidding pasting password is a terrible idea

In some cases, Remote Desktop connection requires the user to type a password instead of copy-pasting it. This is a terrible idea, which is unfortunately used on some websites as well.

When a password is copy-pasted, the user may use long, complicated passwords. If the user is forced to enter the password repeatedly by hand, he will switch to a short password (and if the system makes it mandatory to use digits and symbols, it will also mean a very short and very poor password as well).

What makes sense is to forbid copying a password, especially in a “type password”/“retype the same password” scenario, in order to mitigate the risk for the user to make a typo¹.

Conclusion

Those are a few pieces of advice about passwords. The most important point is to avoid passwords by replacing them by public/private key pairs or by letting another entity, such as Google, handle passwords for you. If both are truly impossible (which should be the case of, say, 0.1% of the systems we use daily), common sense dictates to avoid lowering security by setting arbitrary and technically unwise rules: constraining the maximum length or the characters or setting scheduled expiration.

It should be noted that with a sane policy which doesn't try to annoy the users, the users themselves may be more inclined to use secure passwords. Some may need help to forget about their past bad experiences which pushed them to use Post-it passwords such as “d@ta8asE” instead of easy to remember, fast to type, error prone and difficult to crack passwords such as “завтра разбирать развалины!”. In all cases, when it comes to passwords, users should be helped and trained, instead of forced: there is nothing worse than facing a “Your password is not secure enough” message for an obviously secure password².

An essential aspect is to train users to use password managers. In an ideal world, they would have only one password and everything else will rely on it through a protocol similar to OAuth. In a real world, users are tempted to reuse passwords and since they type them by hand, they are also inclined to use short passwords. A password manager can help by encouraging pseudo-randomly generated, cryptographically secure passwords containing a few dozens of characters which can then be copy-pasted.

If you're still forced to build your own authentication system, make sure you read those answers as well:


¹ It should be noted that I have a doubt about the effectiveness of this approach. Additionally, reseting a password shouldn't be a great deal.

² This was actually the error message I got from Skype concerning my randomly generated account containing 23 to 25 characters with small and capital Latin and Greek letters, digits, symbols. Such stupidity is simply ridiculous and pathetic from a product developed by such a large company.