17

UPDATE: My questions and concerns below boil down to: "Should I reject obviously poor passwords like 'hellomydarling' or 'password'? My guess is yes and I want to know to what extent. I'm using a password strength estimator to assist with that.


I have been doing research regarding usability verses security when it comes to password selection. I came across this very interesting quote I found on this Stack Exchange.

"Security at the expense of usability comes at the expense of security" https://security.stackexchange.com/a/6116/39548

My thoughts and question stem from this. I am working on a prototype for a password strength meter that appears beside new password selection input fields (JsFiddle at the bottom).

The policy I have in place is to make my validator fail if the password is deemed "unusable" by me and to let "better" passwords through.

However, I am concerned about the effect of banning "teenagemutantninjaturtles" but letting "Password must be at least 8 characters" through. Both are bad passwords, but my prototype really only handles the first very well.

This password strength meter is based on Dan Wheeler's zxcvbn "realistic password estimation library" available from https://github.com/lowe/zxcvbn and discussed in detail here: https://tech.dropbox.com/2012/04/zxcvbn-realistic-password-strength-estimation/

I like zxcvbn because it actually uses a dictionary to help identify weak or poor passwords. However, I believe it is too forgiving of plain text pass phrases. For example, it's stock implementation will award the highest possible score (4/4) for 'teenagemutantninjaturtles'.

However, Dan Goodwin at Ars Technica has pointed out that without true randomness, pass phrases aren't turning out to be very effective to thwart motivated attackers ( http://arstechnica.com/security/2013/10/how-the-bible-and-youtube-are-fueling-the-next-frontier-of-password-cracking/2/ ).

So that is why I'm attempting to bolster the behavior of the password strength meter by finding passwords that easily match the zxcvbn's dictionary and simply mark them as "unusable".

For your reference, we disclose that the minimum password length is 6 (even though they suck) and the maximum is 50 chars. There are no other restrictions or requirements. We do not disclose the precise reason why the password is unusable (e.g. it matches a dictionary word, or is to simple, or matches a pattern, etc) although we do provide hints such as those examples.

Here are my actual questions:

Considering that it's very hard for password strength meters to properly evaluate 'good' passwords from 'poor' passwords, when thinking about human behavior and security...

  1. Is it worth it to even include a password strength estimator?
  2. Is it worth trying to bolster the existing library with stricter rules?
  3. Am I just going frustrate my users when I ban a password they think is a good idea? (I'm worried this will potentially cause them to either give up or copy there password to their monitor, etc).
  4. If it is not a good idea, what's the best way to alert users and stop the worst possible passwords?

Note: I am not trying to invent my own security protocol. Once we get the password over https, we store it using via bcrypt with a high cost/iteration. For the sake of argument, let's pretend like this is the only security problem I have left to solve (which it is not).

I am simply trying to encourage better password use for our users.

JsFiddle:

I've copied over my work in progress to a jsFiddle, where my own changes are in the script part (and zxcvbn is an included resource).

http://jsfiddle.net/wsKEy/1/

There's also a lot of commentary and work done to make the password strength meter more usable, which is why there are timers and stuff going on, too.

Thank you for your thoughts.

Niictar
  • 307
  • 2
  • 7
  • possible duplicate of [Are password complexity rules counterproductive?](http://security.stackexchange.com/questions/32222/are-password-complexity-rules-counterproductive) – TildalWave Feb 06 '14 at 18:32
  • 5
    "We do not disclose the precise reason why the password is unusable" - I'd probably just close the website, if I got that reply for a password. Too tired of figuring out what exactly are your rules. – domen Mar 17 '14 at 13:00
  • 1
    Putting an upper limit on number of characters in a password is usually a sign you're thinking about things wrong. Your hash function won't care how long the password is or what characters are in it, and you shouldn't either. Hash it, throw it away, and never touch it again. – Reid Rankin Nov 17 '16 at 04:25

3 Answers3

22

Is it worth it to even include a password strength estimator?

A strength meter? No, because it is too difficult to inform normal users that the "strength" listed is an absolute maximum possible strength, and that their password may be trivially crackable by a skilled opponent no matter what the meter says, while still asking they pay attention to the meter.

A known-weak-password warning? Absolutely! If you can detect that a password is weak, then it's weak. You merely cannot possibly detect whether or not a password is strong, since your software won't have realtime access to the latest in cracking dictionaries, rulesets, and other advances (Markov chains, etc.)

Is it worth trying to bolster the existing library with stricter rules?

Yes! Go take a look at Hashcat for the types of rules it supports, and note that when you have the plaintext user password, it's easy to apply many rules.

  • You can handle all the uppercase/lowercase rules with a simple UPPER() equivalent and an all-uppercase dictionary - if you find it, it's weak. (JacQueLinE)
  • Appending/prepending numbers purely to meet length minimums is a simple pattern match - if the last/first N characters are numbers, and the remaining length isn't enough, it's weak. (Riddick123)
  • Remove N numbers from the beginning/end, uppercase it, and check the dictionary for the remainder (JacQueLine12)
  • The above, but N-1 numbers and/or symbols (#1JacQueLine)
  • The above, but date formats. (JacQueLine02121995)
  • If the last/first N-1 characters are numbers and the last/first is a symbol, and the remaining length isn't enough, it's weak. (!JacQueLine1)
  • Take out one character at a time, see if it matches the dictionary. (jacqu$eline)
  • Combine some of these.
  • Reverse all of these.

Do a pattern-match for dictionary words as subsets, i.e.

correcthorsebatterystaple

  • correct: 1813th most common English word, row 16828 on phpbb, row 9871 on Ubuntu american english small.
  • horse: 1291st most common English word, row 14820 on phpbb (horses is at row 1723!), row 21607 on Ubuntu american english small.
  • battery: 3226th most common English word, row 7775 on phpbb, row 3644 on Ubuntu american english small.
  • staple: 6 characters, all lower case, not in the top 5000 most common words. row 40524 on phpbb (staples is at row 3852!), row 42634 on Ubuntu american english small.

Note that all of these are length 7 or less words; there are less than 21,000 length 7 or less words in Ubuntu's american english small dictionary, 21000^4 ~= 1.9E17, which is more or less 2^58 for a very simple "combinator attack: 4 words, no separators, length 1-7, from this one small dictionary".

Certainly correcthorsebattery would be a much, much weaker password against a combinator attack - 3226^3 ~= 3.3E10 ~= 2^35, using the top 3226 most common English words.

Get some better dictionaries; don't try to send them to the client, host them and the more complex rules serverside. Sure, send the client a tiny one for a first pass, but you need more. Phpbb is the best common small wordlist I know of, then add in rockyou. Many crackers start with brute force for tiny passwords, then small wordlists and large rulesets, then large wordlists - the largest I'm aware of is over 30GB, and includes almost every password found to have been cracked by anyone on a given popular forum, plus many, many other large wordlists.

Find yourself a happy medium - fast enough to be performant, large enough and with enough "rules" to cut out the first few fast passes of cracking software - if you really are using enough bcrypt iterations, then only small dictionaries + large rulesets and large dictionaries + small rulesets will be practical attacks for a few years.

Am I just going frustrate my users when I ban a password they think is a good idea? (I'm worried this will potentially cause them to either give up or copy there password to their monitor, etc).

Yes. When you say "password", "Password", "P@$$w0rd", "P@$$w0rd1", "P@$$w0rd123", and even "P@$$w0rd123!" are bad passwords, you're going to annoy them. When you say "Jennifer2007" is a bad password, they're going to be frustrated (and perhaps Jennifer will be upset, too!). Manage their frustration as best you can, and simply accept some. Personally, I would recommend actually being explicit - tell them their password is a word in known cracking dictionaries plus two numbers, which is a normal cracking rule!

Your purpose is twofold. First, you don't want weak passwords in your system. Second, you want to educate users on what a weak password is, so they have some understanding to mitigate their frustration.

As part of educating, perhaps show them some alternatives you generate that pass your own tests, if you flunk their password.

1) Fully random passwords

2) Fully random passwords translated into bubblebabble or another pronounceable subset

3) correcthorsebatterystaple type passwords, but with longer and uncommon words. For instance, take the Ubuntu american english insane dictionary, subtract out all the words in the american english small dictionary, and select N words of at least 7 characters in length. This leaves you without any really short words, and without the most common words.

4) a mix of 1, 2, and/or 3.

Then your users can, if they choose, simply pick something you showed them (over HTTPS with the best cipher suites you can get away with, of course).

Personally, I would also strongly suggest raising your length limit; about 14 is what I would recommend, but for most userbases that's just too long. Try a minimum of 12 or even 10, enough so a fully random password might have a slight amount of value at the minimum length and character set.

Anti-weakpasswords
  • 9,785
  • 2
  • 23
  • 51
  • 2
    Can I upvote this answer twice? The second time for "Second, you want to educate users on what a weak password is" –  Mar 21 '14 at 20:44
  • Aren't two short words better than one long word? Even if not, I wouldn't disallow them, I'd just require some minimum total length instead. – maaartinus Aug 05 '17 at 12:51
  • @maaartinus - that gets very difficult to judge. Certainly a password with "be the" (https://en.wikipedia.org/wiki/Most_common_words_in_English lists them as the 2nd and 1st most frequent English word) is going to be less secure than one with "alysm", also exactly 5 letters, since simply taking a top 20 wordlist and going cartesian with itself will find "be the", while you'll need to search more than 20^2, or 400, words to find a rare one like "alysm" that isn't on any top 10, top 100, or top 5000 lists, nor is it in the smaller English dictionaries of more popular words. – Anti-weakpasswords Jan 08 '18 at 05:52
7

A "password strength meter" does not measure the absolute strength of a password. What it measures is how fast the designer of the "meter" would have cracked the password, generically and without context. The "meter" would try a number of passwords in some order, and the strength measure is just how far the actual password is in this list of potential passwords.

In that sense, a "password meter" can only overestimate the strength. If the meter says "31 bits of entropy", it really means "I could have broken that in 230 operations, so it cannot be stronger than 31 bits". However, the password could be much weaker. The really important expression in the paragraph above is "without context". This is not a very realistic assumption. The attacker attacks the password because he is interested in attacking the password, meaning that he has some notion of what is protected by that password. He may also have some information on the password owner (e.g. his name, email address...).

For instance, just imagine how many Facebook account passwords really are "F4ceb00k7823": if your password meter does not know that it is evaluating passwords meant for Facebook, then it may miss how the first 8 characters of the password contribute almost nothing to the total entropy.

Get a password meter and see if you can fool it with a "witty" (but weak) password. It is easy. It is fun ! E.g. the demo will give a whooping 39.218 bits of entropy (cracking time of 13 months !) to nothing less than "BarackObama". Now that is a strong password ! (Strangely enough, "BillClinton" and "VladimirPutin" rate much less.) More to the point, average users will also play such games, and find it fun. That's the problem. A password meter is doomed to have some failure cases like this one. Some of the users will use the password meter as an excuse for weak passwords. Others will believe that they have a strong password; a false feeling of safety is about as big an issue as a voluntarily weak password.

Password meters can be useful as a behind-the-curtains tool, to gather statistics on passwords as chosen "naturally" by users, so that you may know what you should say during security awareness training. However, making the tool available to end users invites trouble: some will play with it, others will feel protected by it, and the general security level will decrease.

A policy of "no less than 8 characters", on the other hand, is acceptable, because:

  1. No password of less than 8 characters can be deemed strong, because it will fall to the stupidest of brute force attacks.
  2. Users understand why short passwords are weak, and will cooperate.
  3. There is absolutely no fun whatsoever in finding a password which is not rejected by the "no less than 8 characters" rule.
Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • 'hellomydarling' is 14 characters long and is a terrible password. Also, 'password' fits 8 characters wonderfully. Is it ok to let those examples slide because we don't want to frustrate our users with any additional rules? – Niictar Feb 06 '14 at 18:47
  • There is normally no problem in rejecting _obviously_ bad passwords as long as they are _obviously_ bad -- that is, even from the point of view of the users themselves. But that's rather restrictive. Also, it still promotes a game of "finding the limit" which unfortunately implies that weak passwords are used. And you really _really_ don't want your users to feel frustrated, because security relies on their cooperation, and frustrated users don't cooperate. – Tom Leek Feb 06 '14 at 19:06
  • Okay. That's a big part of my concern. Someone might think 'hellomydarling' is clever because its "longer" and is a passphrase no one will could guess that individual would choose _that_ password use on _this_ particular account. So banning it could potentially frustrate that user. Then again, we are courting corporate clients, not home consumers... – Niictar Feb 06 '14 at 19:18
4

You mention creating a password meter, yet you really seem to be interested in banning "unusable" passwords. Rather than a meeter you may be better served by a simple check mark, or red X to indicate whether it's acceptable or not (simpler for users). If their password doesn't meet your complexity, you may consider including suggestions on how to make it conform.

I notice that zxcvbn calculates entropy of a password using lists of patterns, which is probably why 'tenagemutantninjaturtles' passes (it's likely not included in the list). You may consider tweaking the entropy calculation. The amount of actual entropy in 'tenagemutantninjaturtles' is pretty little. The example has a very limited range of characters, which on traditional strength checkers would fail (no capitals, numbers, special chars). Simply modifying to 'TeenageMutantNinjaTurtles1!' would bypass most naive checkers though. You may consider placing a weight on chars near the beginning or end, making special characters/numbers/caps only count for a portion of the required number.

Another solution could be to run the password through Wikipedia. A Wikipedia search could capture references that a simple syntactic search wouldn't.

  • Yea, my implementation ( http://jsfiddle.net/wsKEy/1/ ) takes advantage of zxcvbn's dictionary matching and would find 'tenagemutantninjaturtles' "poor" (1/4) and 'TeenageMutantNinjaTurtles1!' would be rated "average" (2/4). But this might all be simpler if I just change it to an X and a check mark like you suggest. I'm not sure what method would encourage better account protection overall. – Niictar Feb 06 '14 at 19:49
  • 3
    You could always scrap the "scoring" of passwords at creation, and just do a simple regex requirement (8+ chars, upper, lower, special). Periodicly you could dump the password hashes and try to crack them yourselves. Let the cracker run for a day or so and any passwords cracked get "reset/locked" and the user has to choose another. That's the MOST real world way to determine password security. – waitingToCompile Feb 06 '14 at 20:24
  • You can't write a secure password validator that validates passwords by calling an external (and untrusted) search engine. Otherwise, every password you test immediately becomes unsafe because you just handed it to someone else. – Johnny Feb 06 '14 at 22:53
  • 1
    @Johnny, waitingToCompile may be talking about the offline wikipedia database. – Daisetsu Feb 07 '14 at 01:50
  • @Niictar But `TeenageMutantNinjaTurtles1` is exactly as strong as `teenagemutantninjaturtles1`, if not weaker as people usually capitalize words. Something like `teeNageMutantninJaturtlEs1` is stronger by maybe 10 bits. – maaartinus Aug 05 '17 at 13:02