Recently I had a shower thought about passwords, namely that any rules we apply limit the possible passwords the user can choose. Which also means that there are less passwords an attacker has to go through when brute-forcing a password.
For simplicity I chose 4 character groups:
- lowercase letters: 26
- uppercase letters: 26
- numerals: 10
- special characters: 34
The calculations assume that there has to be at least 1 character of each group in the password.
This is not exhaustive of course, but I have to start somewhere.
In total there are 96 allowed characters.
This means, for an 6 character long password, without any rules, there are
782.757.789.696, options. Almost 800 billion.
With the rules above applied, there are only
188.8.131.520, options. Just a bit more than 2 billion.
That's a 370x difference!
To put that in perspective, instead of 1 year, it will take an attacker less than 1 day to brute-force that password.
Is that bad?
To be honest, I don't know. It sounds like much, but on the other hand, increasing the length by ~1.3 characters will negate the difference. So a password that's 1 character longer will almost do so, and one that's 2 characters longer will provide even better security.
What are your opinions on that topic? Please comment below 👇
Follow me on Twitter for more of my thoughts, articles, projects and work.
Top comments (25)
Ideally, I'd rate limit the auth api and check against a list of commonly used passwords (and against a db of previously compromised usernames/passwords), then ditch the rules and stop worrying about brute force.
Agreed, to stop someone brute-forcing login page is to temporary ban that user from loging in after getting password wrong 3-5 times.
It's a bit different when someone gets hold of your DB so there's no way for you to limit how many tries they get, and the hashed PW probably includes method meta-data.
Password rules/strength checkers should be clever enough to know tho that after certain length, some rules can be omitted.
And because 99.9% of people just do Capital first letter + lowercase rest of the word + easily guessable number (birthday, etc), or they use simple replacements like O is 0 or A is @, etc - it's relatively easy and quick for hackers to get around having to try every combination.
That's an interesting point. So even if every character is allowed in a password, an attacker could still only try combinations with lowercase characters + numbers, since most users will only use that.
So in this case, if the attacker only wants to find out a majority of passwords, those rules actually increase the password space.
Would probably be different for services that target developers though.
Apparently so. I dunno. I go for length and simplicity my own accounts :)
Your users... Got few mates in hosting business, they constantly have to deal with hacked WP installs because people don't pick good passwords :|
I wonder what a cost/benefit would look like for keeping salts in a separate database from the hashes. Would be helpful to know more about the specifics of large intrusions.
I don't know that much about cryptography to really make valid argument either way.
I imagine in some ways you will have a lot more to worry about with race conditions where one DB is in sync, the other isn't.
Great, so now you can ban any user you want my spamming requests to the password endpoint so they get temporarily banned.
Can rate limit by ip address as well as by user. Could also leverage machine learning to detect anomalies in auth rate.
IP limiter is another good option too yes.
Also, you don't have to email user that their account has been suspended for 15 minutes every single time.
People a lot smarter than me already have concluded that password length is all that matters, any other rules will only reduce the effect because people will use more predictable passwords. This combined with special slow hashing algorithms designed for password storage (e.g. bcrypt) is how to handle passwords.
This is just for passive password security, for when the credentials storage is leaked.
For the active service you obviously want to add MFA, temporary account locks, additional verification like recaptcha.
There also this nice XKCD:
NIST recently loosened recommended password length and complexity. Basically, they found that strict password policies just lead users to do things they should not be doing like reusing passwords, writing them down on post its because they are hard to remember, transposing letters with numbers so they can use dictionary words, etc. This is a much bigger problem because it facilitates things like social engineering.
Instead of putting the burden on your users, verify their passwords against blacklists, recommend they use a password manager (with random generated passwords), implement 2FA (and soon webautn), and rate limit your APIs to prevent brute force attempts. That's a good start. If you implement length limitations at all, go for something like 16 characters. Anything less is technically not really that helpful against brute forcing and chances are that users just add something like 12345 to the passwords they use elsewhere that is already on a compromised password list (i.e. trivially brute forced).
And for the love of god, use bcrypt with salted hashes (especially if you don't know what those are). Nothing else is even remotely acceptable. Don't even try to reinvent/improve that stuff. There are perfectly good OSS implementations for just about any popular language out there that have been properly audited, battle tested, etc. If you are not using those, you are doing it wrong.
Requiring one of each special character doesn't narrow the attack space. You have to remember that the attacker doesn't know the password unless it's guessed correctly. They don't know the order and which characters satisfy which requirements. Therefore to the attacker, every character could be any of the 96. Character requirements enforce that a user takes advantage of the full character space and that the attacker has to try 966.
What if the attacker knows the rules of the system, though? If I were an attacker and I know that the password is exactly 6 characters and at least 1 special character is required, I don't need to bother checking
Right, but it's a trivial difference. A difference more than made up by the fact that all your passwords had to be brute-forced in the full attack space. If for argument sake we keep a password of six characters with the full allowable space of 96 would be 966. A password of six characters using the full space with a required one special character would be (965) *34. The difference in those two spaces simplifies to 96/34 or ~2.8x. Consider now that without the requirement, you could try guessing passwords in a 26 or 52 character space, knowing that it is likely some percentage of people only had lowercase or alphabetic passwords. That would be a much smaller space and would probably yield a decent number of passwords. Ultimately length matters more than anything, and perhaps requiring a special character creates more attack vectors through social engineering. Real world security is hard all the way around I guess.
Also, I'm not sure were OP got 270x... Is my math wrong?
I calculated it for all rules together. 1 lowercase, 1 uppercase, 1 digit, 1 special character.
96^4 / (26*26*10*34), which is about 370.
But they do know the password rules. So they can eliminate all passwords that don't satisfy them, and not even check those.
I believe that since the problem is solved by adding a couple more characters to the password it is not really an issue. We are not talking about getting the length up to 20-25 characters but just to 9-10. Which is still quite easy to remember.
Sure, it takes away all the combinations that use characters from some instead of all the character groups you mentioned but it is easily negated by the password length.
Plus the number one rule to make your password "immune" to brute force is making it longer than 8 characters (by today's standards, correct me if I'm wrong). Most of the sites that test passowrd strength suggest so.
I guess the question is actually all about psychology. Is this really not a burden for the user? 1-2 characters don't sound that much, but for some it might make it too hard and they write it down somewhere. It's not just about crackability.
On average one could probably say that, but it actually depends on the hashing algorithm. If it takes 10s to check one password, then a lot fewer characters are needed. And if md5 is used, the longest password on earth won't help you.
It is a burden! Ideally each user has different and difficult passwords for each account he owns. This makes remembering all of them really hard but fortunately we have password managers to do that job. They generate long random passwords and the user just remembers only one really hard one, which is totally doable.
In a perfect world everyone is using one of those and every website has secure and updated password storing.
Yes, I think the theory is correct, but the practice is different.
You presume that the passwords are random, so the avg number of guesses is close to the median. In reality people will use same common passwords and the guesses will be sorted by popularity. By enforcing these rules I suppose it is a forced way to enlarge the set of common passwords.
I personally hate these rules, because I cannot use the most secure passwords and easy to remember (which are a long set of common words) :(.
You're right, that's very similar to what I've realized from that comment.
I somehow never thought of passwords being sorted by popularity, just going through them in order.
If you set up your rules to say that you need to match at least
ncriteria, such as "> 1 special character", "> 0 uppercase", "total length > 20 characters", etc. then you can keep that magic number big. Explaining these rules to a user in a clear manner is more difficult though.
I think Anton Frattaroli and Michiel Hendriks have it covered well. But I'll add my two cents anyways. I don't use a PW manager because I don't trust them ... eggs in one basket and maybe the basket, etc.
My technique is modelled after the security ring system. I have several levels of password from easy / non secure to hard (hopefully very secure). The one or two easy rings never change and they are used for things like newsletter / website subscriptions and blog posts. From there I use a system. I change the system every 3-6 mos. The most secure ring is email and the next secure is banking and credit cards.
For example, a system could be based on flowers:
step 1: choose a number of flowers or flower phrases from easy to hard, use camel case for phrases:
Step2 Leet the vowels and special character some letters
Step3 - append or prepend the name or abbreviation of each website:
So, for Amazon which would be a banking / credit card site:
Chry$4nth3mum$-Amazon becomes Chry$4nth3mum$-4m4z0n
Then every so often change the formula ... cars, animals, mineral names, state capitals, cities in Europe, etc.
I think enforcing numbers & special characters reduce the odds of a simple dictionary attack.
BTW, usually special characters are limited; encoding & such.