Inferring password storage security through maximum password length requirements.

I’d like to follow up on a fairly obvious thought I tweeted today:

If a site has password length limits, it’s probably stored in plaintext. Hashed passwords (of any size) have a predicable length.

Excuse the typo, please. Explanation:

The sane operating procedure for password storage is to use a hash function (md5, sha256, bcrypt and similar) along with a “salt” to one-way hash the password. This hash is a known length, no matter how long the password is. For a hexidecimal md5 sum, it’s 32 characters.  When a user comes back to authenticate, you take the password they supply and the salt, calculate the hash, and match it against the hash you have on file. If the newly calculated sum matches the one you have on file, the user has entered their password properly.

There’s no logical reason to limit a hashed password’s length: a 4 character password and a 4000 character password will both calculate to the same size hash.

So if a website has a maximum password length, it means they are probably NOT hashing it and the limit they apply is to keep you from exceeding the column length of the table they store it in.  @abackstrom pointed out here that it’s probably the same situation for disallowed “special characters” - they shouldn’t care what you enter if all they are doing is hashing your password. If they do, they are probably storing it directly in a database.

Why is this bad? Many obvious reasons:

  • Your unencrypted password is sitting in a database, waiting to be stolen if/when the site in question is compromised,
  • Many people share passwords amongst websites, so a list of email addresses and unencrypted passwords can lead to many more compromised accounts on sites all over the web,
  • It’s unnecessary. There’s almost no valid reason to store an unhashed password, especially with all the excellent authentication frameworks out there.

What can you do?

If you’re a website user, complain! If a website has a maximum password length or a restriction against special characters: contact them! Tell them you don’t appreciate their lax security.  Ask them to support openID, ask them if they store passwords unhashed, just let them know this is important.

If you’re a developer, use an authentication library known to do things right in your language of choice. Don’t write your own, busted, authentication system.

This work, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

4 thoughts on “Inferring password storage security through maximum password length requirements.

  1. The ban on special characters is of course due to paranoia about SQL Injection. It wouldn’t surprise me if sites that banned special characters from passwords were also more like to stored passwords as plain text. However, you could still have a SQL injection even if the site was only storing the hash. For example,

    “SELECT * FROM USERS WHERE USER=$user and passhash=hash( $password )”

    One would hope that a site is using parameterized SQL queries throughout but input validation can be a good defense in depth strategy especially when there’s a large code base.

    That said, I think banning special characters from passwords is a bad idea. It makes passwords much easier to guess or brute force leaving users more vulnerable and doesn’t really do that much to protect the site itself.

  2. good points here, I think this is why two way autentication is catching on- I am in charge of our product roadmap, this blog and others will make me focus more on security.

  3. It’s also worth mentioning that when a website lists off the (arbitrary) restrictions that they impose on user passwords, it gives attackers the info they need to tune their attack parameters!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>