Password:
  
*
|
TGP Password Strength Checker
For ease of navigation, I've moved the TGP Password Strength Checker
documentation here as it makes more sense now that the on-line version is available.
Full TGP docs are available
HERE.
This is a screenshot of the TGP implementation and associated docs.
|
|
I think the PasswordStrength qualifier is very valuable. Administrators tell
users that their password must be "complex" (which users hear as "difficult")
but they don't tell us what makes a good password/passphrase "good."
Password strength meters I've seen simply make a Best Effort to say "bad,
good, better" or some ambiguous qualification. But nothing ever actually
quantifies a strong passphrase. I wanted to do something differently - as
such, I've decided to add a measurable and valuable attribute where I actually
calculate how long it would take to crack the keyspace of the password you've
selected based on they "base" characters you use. I look at
it this way: To really pick a good password, you should assume the best case
scenario for the attacker, and the worst case scenario for you. When
an attacker brute-forces your password, they basically iterate through all possible
character combinations. a-z, A-Z, 0-9, the top row !@#$%^*()-=_+ characters,
and then other printable characters like ~, {,>, etc. Of course, it is
not always like this, but it is typically how they go about it. If you enter
"abcd" as your password, that being 4 all lower-case characters, the attacker
shouldn't know that, but you can't be sure. If they DO know that,
then you are toast.
|
|
So let's talk math. The reason for this is that all an attacker has to do is iterate
through all possible combinations until they get your password - in this case, begin
with a, and loop through over and over. The entire keyspace to guess
a 4 character lowercase password is 475,254. Oh, one thing - almost all the
"brute force" crap I see on the internet tells you that brute forcing
a 4 char lowercase password is 456,976 (or 26^4). That is incorrect - the
iterations would only be 26^4 if you STARTED OUT with 4 characters as the base ("aaaa")
instead of starting at "a." You've got to get to "aaaa"
first by going through "a," "aa," and "aaa."
To properly computer this, you would have to use 26^4+26^3+26^2+26^1 as your
formula. The difference between 475,254 and 456,976 may not seem like
much, but there is a 5.6 trillion iteration difference just when you get to 10 characters.
So right from the start, systems using that formula are simply wrong. TGP
calculates the entire brute-force effort required to get there from "a"
where an attacker would start. Further, I look at the password and try to
determine the minimal base keyspace it uses. If you type in "abcd"
then I'll only use a-z. If you type "abcd1" then I'll give
you a-z and 0-9 (increasing the base to 36). If you type "abcD"
then you get a-z and A-Z, or base 52. If you use "abcD1" then you
get base 62. A "!" or "&" character gets you to base
76, and finally a "[" or "~" then you get the total 96.
Now, I obviously have to make some assumptions here,
but there's no other way to do it (that I could figure out). Deriving
the base from what an attacker would have to use makes sense to me. Combining
that with the "known" information of what you are typing in makes even
more sense. So that you know, I'm assuming what an attacker would have
to assume if he knew some of what you know (as odd as that may sound). So
I group the bases as "a-z," "a-z,A-Z," 0-9, "!" through
"=" and then everything else. So if you type "A" I have
to assume that you've probably got lower case in your password. So a single
"A" is up to 52 possibilities since I count lowercase. 0-9 is always
just added in when used - "a1" is 36 (26+10), and "A1" is 62
(52+10). A single "!" is 76, so "A!" is base 76.
A single "[" is 96, so "A[" is base 96. So finally,
if you had "Ab44!" then the entire keyspace would be 76^5+76^4+76^3+76^2+76^1
or 2,569,332,380 combinations. For reference, the actual base
characters I use are broken out as follows - these "base" character sets
are what correlate to the "Keyspace Derives 'x' of 96" above
in this order:
|
Base 10:
|
0123456789
|
|
Base 26:
|
abcdefghijklmnopqrstuvwxyz
|
|
Base 36:
|
abcdefghijklmnopqrstuvwxyz
0123456789
|
|
Base 52:
|
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
|
Base 62:
|
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
|
|
Base 76:
|
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
!@#$%^&*()-=_+
|
|
Base 96:
|
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
!@#$%^&*()-=_+
[]\"{}|;':,./<>?`~
|
The above groupings are just how I chose
to organize character sets based on how I’ve seen different crackers implemented,
and the way I’ve seen the propensity for people to group top-row special characters
together like T$i*D3 as opposed to T$i]D3. There is nothing in the 'hacker handbook'
that says you check for any particular special characters in order, other than some
that iterate in ASCII order, but I try to group these the way a person would create
the password even though it is a computer cracking it. There is no "right
way" and there is no set 'hackers do THIS' way. Just know this
as you think about how this applies to your password policy. No, I
didn't forget A-Z 0-9. I just didn't find value
in all upper and digits as I normally don't see that. I see all lower and
digits because it is the default. That's not to say passwords won't be all
upper with digits, but rather, that I have chosen to have represented by base
62, and that all upper and digits is mathematically the same as all lower and
digits, so just use that if you really want to use a limited keyspace for
upper+digits.
Now - with THAT information, I take the highest class of cracking (Class F) which
is 1,000,000,000 attempts per second. That's a bunch. Again, I want
the worst case for you so you know how strong your password is. I then calculate
the amount of time it would take to crack the keyspace of your password and display
that. In the above case of Ab44! the entire keyspace would take a whopping
2.56933238 seconds to crack! That should tell you something. It may
be considered "complex" since it has upper, lower, numbers, and a special
character, but 2.5 seconds isn't that much. Granted, most ankle-biters
with a cracker will only get a few 100,000 per second, but we have to be sure.
And this is where the power of this type of analysis comes in - don't tell your
users to have a "strong" password (whatever that means), but rather, require
that they have a password that can withstand a Class F attack for X time (whatever
you decide). That way you have something you can MEASURE. And that's
good. So let's look at the above screenshot - I used "aaaaaaNotGood"
as the password. That's 13 character mixed case characters. The
keyspace to attack that would take 650,000 *years* to crack at Class F. Seems
strong, right? Well, that's what got me to thinking. Again, I let
myself limit my imagination by looking at it from the attacker's view.
Why do that when I *know* the password I'm entering? That's when I
decided to write an algorithm to calculate the iterations required for the actual
password I ENTERED to be reached, and not just the entire keyspace.
THAT's where the real value comes in. Don't just quantify the keyspace,
quantify the actual password. The algorithm I wrote worked well, but
it was not super-fast -- so I'm using a formula my buddy Will Fischer came up
with (Thanks Will) since it's better than mine. He's actually
helped me quite a bit with this, so thanks^2. Since we know the password,
we basically calculate out the steps required to hit each individual letter in each
column based on an index string I define in memory from "a" on.
That string allows me to easily determine what the character is a column (character)
at a time, for each character in the password. I then compile the column-by-column
data into a final "iterations" value that is then in turn compared to
Class F. As such, we see that the 650,000 year keyspace for "aaaaaaNotGood"
is reduced to 12,637.66 years since I chose to begin my passphrase with 6 lowercase
"a" 's. Simply changing the first "a" to an "H"
takes the calculation from 12,637.66 years (based on 398,541,262,291,912,000,000
combinations) to 13,297,482,476,338,200,000,000 iterations, or 421,660.40 years.
Still a big difference between an "a" and an "H" and the overall
20,724,145,598,800,400,000,000 iterations for the keyspace at 657,158.35 years.
* 07/17/10 User configurable brute force
class selection added.
Wayne Anderson (fellow Focus-MS poster) and
others have suggested that I add a user selectable value for the brute force class.
Well, here you go.
I actually thought about doing this when I first wrote the tool, but I wanted to
make sure that the user saw the “worst case scenario” for cracking. If you build
your password strength from the worst case, that being a Class F at 1 billion iterations
per second, then you really don’t have to worry about attacks on slower platforms.
However, I can see the value in being able to select your own class.
Part of the reason for this is so that you can see what a “real world” attack will look like. Not
everyone has the NSA trying to get to their data. Also, I think it is valuable for
when you don’t get to choose your password strength and want to know how much risk
you are at by normal, everyday attackers. For instance, take the following screen
shot from a Cisco product:
In this product, you had to create an Admin user. But note the restrictions: “Your
password must be less than 8 characters and cannot contain spaces or special characters.”
Nice. Thanks, guys. In these cases, I’m forced to use a crappy password. Selecting
the worst case for the attacker, a Class A attack at 10,000 per second (which
your printer could probably do in its spare time), you get a max of 61 hours to crack
the keyspace of a base 62 (a-z,A-Z, 0-9) password. Something like AaZzaa99 cracks in 26 hours.
When you consider this, Wayne has a point that this type of "lower class" attack could be valuable.
I never thought I would care about low class attacks. Ba-dum.
This also could provide you some insight when it comes to how
secure certain other restricted and default passwords are. For instance, let’s just
do a quick search for “mailing list memberships reminder.” This
query will provide all sorts of links to archived emails where the admins of mailing lists didn’t
think about how their reminder notices to users, which contain the full username
and password, are archived to lists and thus index-able via your favorite search
engine. While we won’t need to crack these as they are already clear-text, you
can see how most are simple lower-case 8 character random characters. You can brute-force
the entire keyspace for that on the slowest class there is in only 217 seconds,
or roughly the time it takes to listen to AC/DC’s “Have a Drink on Me.” Nice.
NOTE that the checker automatically changes the labeling to reflect seconds, minutes,
hours, days, and years. So if you are mucking about with a password class and see
that the number doesn’t change dramatically, it’s probably because you are crossing
the boundary for the unit of measure being presented.
Dictionary attacks and other attack methodologies:
The first thing the l33t hacker-types will say is "what if I start with Z and
go backwards, tough guy?" Then they do that. Whatever. If
you are really worried about it then get your calculator out and figure out how
long it would take going backwards. Or just start everything with "M."
Of course, they might then decide to start in the middle on the off chance that you did
that, and so on and so forth. It is an argument of diminishing returns.
|
WTF is a BananaDog?
|
I think the same sort of logic applies to dictionary attacks -
Will and I call this the "bananadog" syndrome. (The
reference to Will originates on the TGP docs here.
I moved this text since then). That's where
you can have a dictionary of 10,000 words, and use it to attack people who are so
dense that they use "banana" or "dog." Let's say you double
up on the words (100,000,000) so that if they were very clever and used "bananadog"
the attacker would still get it in milliseconds. Thing is, the "bananadog"
keyspace would only take about 94.11 minutes to crack. In that time, the attacker
would get any possible combination of 5,646,683,826,134 lower case, up to 9 character
passwords. Any of them. The "bananadog" attack will always
be limited to 100,000,000 total possible passwords, and will miss things like "bannaadig"
. Attackers want your password, so they'll make sure they get it.
As such, I'm not worried about bananadog. And if you are the bananadog
type, I doubt you would be reading this anyway.
Will's point, and it is a good one, is that if I as an attacker can spend a
couple of milliseconds getting x passwords up front from a dictionary attack, why
not do so? And I agree. The logical extension of that is to build some
sort of sanity check in the password strength checker to weed out BananaDogs.
And I may do this. The difference is the level of assumption one must make
- meaning, the actual application of dictionary attack logic is very subjective,
where the brute force assumptions made around ordering attacks (in regard to a-z,
A-Z, 0-9, etc) are fairly established by current implementations. Do I concatenate
words to score BananaDog? Do I do it 3 times to score DogBananaDog?
What about BananaDog1? or B4n4n4D0g? I find the application of dictionary
attack logic too "random." It certainly can be done, but I don't
know how applicable it would be to build into a tool. As such, I'm putting
that on the back burner. If anyone has any suggestions around that, feel free
to contact me at {thor at hammerofgod dot com}.
So that's that. The above checks are made when you generate your keys
so that you have the little extra bit of security.
|
|
|