Allowing long passwords is good but could also be used as an attack vector
It’s good practice to allow your users to have long passwords. These passwords can be stored as a hash and because the hashed version is a predictable length, the password can be stored in a database without worrying about it being too long for the column’s length limit.
Allowing long passwords turns out to be a double-edged sword – and one I’d never considered. I was reading about a denial-of-service attack that was used against a website (built with Django in this case), where an attacker had used the plain text login password as an attack vector to bring the site down. What the attacker was doing, was posting really long passwords knowing that the encryption of the password was computationally expensive. By sending multiple login requests in a short period of time with long passwords they were able to max out the server resources preventing anyone from being able to access the site.
Django was using PBKDF2 to hash the password. PBKDF2 is designed to be computationally expensive so that password cracking attempts take longer. Bycrypt and other hash functions are also designed to work this way. Even with a simple MD5 hash, which is fast, it will get progressively slower the longer the given string it is hashing is.
Fortunately the solution is simple (and has been fixed in Django for a long time), check the length of the password submitted to the server. If the length of it is not something sensible then reject it before performing any computationally expensive operations on it. This of course is not just limited to passwords, it can apply to any data that you encrypt.
I’d allow passwords of at least 1,000 characters – some password generators I’ve seen will give you a 2,048 character password. The attackers were using passwords with millions of characters in. I can’t see why a real user would have a password longer than that long so would block based on that.
Using a password 1,000 characters long took 11ms with the PBKDF2WithHmacSHA1 Algorithm in a test I’ve just run. It’s when my ‘password’ is 10,000,000 chars long you start to see a noticeable impact (~300ms in my basic test). With no limit you can submit much longer password strings. Although 300ms may not sound like much, if you’ve got multi-requests coming in all taking 300ms you will start to run out of resource.