views:

253

answers:

3

I'm not that hip on the L33t language beyond what I've read on Wikipedia.

I do need to add a dictionary check to our password-strength-validation tool, and since leet-speak only adds trivial overhead to the password cracking process, I'd like to de-leet-ify the input before checking it against the dictionary.

Edit - To clarify the reasoning behind this: When required to add symbols to their passwords many users will simply do some very predictable leet substitution on a common word to meet the number and symbol inclusion requirement. Because it is so predictable, this adds very little actual complexity to the password over just using the original dictionary word. \Edit

Not knowing all the rules, especially the multi-character substitutions like "\/\/" for "W", and being certain this is a problem that has been addressed many times including certainly by open source projects...

I'm looking for code samples, but haven't found any so-far. If it is C# code that would be a bonus!, but code in any common language will help.

Also, it would be nice to have an extensible approach, as I understand this dialect evolves quickly. It would be nice to be able to add-in some rules in a year as those evolve.

Thanks.

-Edit-

FYI, no this is not the basis my entire password strength check. This is only the part I am asking for help on in this post. So we are not distracted by other elements of password and security concerns, let me describe the password concerns that don't have to do with leet-speak:

We measure the bits of entropy in the password per NIST special publication 800-63, and require a policy-configurable equivalent measure (56 bits for example) for the password to be valid. This still leaves room for dictionary words that have been simply leet-ed and from an entropy perspective aren't a whole lot better plain dictionary words.

I would simply like to tell users that "P@s5w0rd" is too close a dictionary word, and they could probably find a stronger password.

I know there is a lot more to security considerations like the balance between passwords that humans can remember, and passwords that are secure... This isn't that question.

All I'm asking about is converting l33t to plaintext which should be nearly as fun and interesting of a topic as code golf. Has anyone seen any code samples?

+11  A: 

I must say I think this is a bad idea... If you want them to be strong, come up with better requirements.. must be at least 8 characters, contain upper AND lowercase letters, contain at least one number, and at least one special character. Implement a maximum authorization failure counter before disabling an account. Once that's done, what are you worried about?

Fosco
+1 for better direction, more relevant security principles.
andyortlieb
Have to say, I agree :) "De-1337-ifying" is not trivial at all. A quick example would be that '4' == 'a' in 1337, soo, do you want to disallow all 4's?
cwap
I think the op wants to prevent passwords like "l33t haxx0r", which is pretty trivial and probably rather common. It has 8 characters, at least one number, and a special character, but is not secure.
Stephen Cleary
@Stephen even then the OPs question wants to de1337ify that... and they would get something like "leet haxxor" or "elite hacker" depending on what rules they follow, they would be better off adding "l33t haxx0r" to the dictionary of bad passwords.
Shaded
@Stephen Cleary then a better idea might be to add common l33t-speak phrases like 1337, h4x0r, etc. to the dictionary and don't allow passwords to contain substrings of those words.
Jonathon
I don't think the OP is only interested in common 1337 wordings, like h4x0r etc., but also the usage of 1337 in a password to conform to his rules. For example, if I normally use "escobar" as my password, then he won't allow "esc0b4r" -- Well, at least that's how I interpret his problem description :)
cwap
@Jonathon: I agree with you. I was just pointing out that this answer doesn't really address the OP's problem - he is already planning on defining strong password requirements.
Stephen Cleary
Well, just like trying to help someone in the "business" when you're in "IT," sometimes you have to explain that what they are asking for isn't really what they want.
Fosco
Thanks all. Many of these suggestions are already in-effect in the system, I didn't mention them because they weren't terribly relevant to the question. I have a complexity measure in in terms of bits of entropy as per the NIST publication on the subject. passwords must be at least equivalent to 56 bits (configurable by policy). But a dictionary check is an important suplement to that. "P@s5W0rd" may pass simple regex checks, and even look like good entropy, but it is not a good password because it is a dictionary word that has been leeted which adds trivial overhead to a dicitonary attack.
DanO
@DanO: Why would you be vulnerable to a dictionary attack?
Fosco
Hopefully we are not. There is a principle in security known as defense in-depth. Even though we lock-out after say 5 failed attempts, and take other precations is is best to have multiple layers of defense rather than relying on any one layer... strong as it may be.
DanO
If the unthinkable happend and someone obtained our hashed passwords from the database, they could easily run a 10,000 word dictionary against those hashed for matches. They only need one user to have used a dictionary word. Add-in simple leetification (the way many user add required symbols) and the attacker could add 5 leet variations to each dictionary word and still only be at 50,000 hashes they need to perform. That is only equivalent to an 8-bit key
DanO
@DanO I hear you and I'm not trying to be difficult.. I added some code in another answer. I feel like I have to be snarky though and mention that if someone obtains your hashed passwords, leet speak is the least of your problems :)
Fosco
@DanO 50,000 possibilities would be about a 16-bit key not 8-bit. Oops.
DanO
+4  A: 

Also offering some code::

        String password  = @"\/\/4573Fu|_";
        Dictionary<string, string> leetRules = new Dictionary<string, string>();

        leetRules.Add("4", "A");
        leetRules.Add(@"/\", "A");
        leetRules.Add("@", "A");
        leetRules.Add("^", "A");

        leetRules.Add("13", "B");
        leetRules.Add("/3", "B");
        leetRules.Add("|3", "B");
        leetRules.Add("8", "B");

        leetRules.Add("><", "X");

        leetRules.Add("<", "C");
        leetRules.Add("(", "C");

        leetRules.Add("|)", "D");
        leetRules.Add("|>", "D");

        leetRules.Add("3", "E");

        leetRules.Add("6", "G");

        leetRules.Add("/-/", "H");
        leetRules.Add("[-]", "H");
        leetRules.Add("]-[", "H");

        leetRules.Add("!", "I");

        leetRules.Add("|_", "L");

        leetRules.Add("_/", "J");
        leetRules.Add("_|", "J");

        leetRules.Add("1", "L");

        leetRules.Add("0", "O");

        leetRules.Add("5", "S");

        leetRules.Add("7", "T");

        leetRules.Add(@"\/\/", "W");
        leetRules.Add(@"\/", "V");

        leetRules.Add("2", "Z");

        foreach (KeyValuePair<string,string> x in leetRules)
        {
            password = password.Replace(x.Key, x.Value);
        }

        MessageBox.Show(password.ToUpper());
Fosco
I think a map leet=>unleet would be better, as you wouldn't have to type leetRules.Add for every pair.
tstenner
Thanks, that is perfect. Extensible, simple. These substitutions could be in a file to make it even more extensible. The suffixes like -xor and -zorz could just be removed. Is there no more to leet than just this substitution cipher? Wasteful? Interesting choice of password.
DanO
I though there might be more grammar involved with leet than just substitution. Dealing with grammars was one part of CS I didn't care for.
DanO
As far as building on this to support grammar and additional replacements, the function would likely never return just 1 result from an inbound password. If you want to be returned an array of every possible replacement (i.e. h4ck = hack, hax, haxx) then I could assist in expanding it. As it is now, I ordered some replacements specifically to not mess up replacements taking place later.
Fosco
+1  A: 

Why don't you just implement a function to just create "pronounceable" passwords and require users to use them? It seems like much less work and better security.

Jay
This is good suggestion, and an interesting idea, as user generated passwords do have inherent problems most of the time. In this case though, users need to be able to choose their own password, and we just have to make sure it is strong enough. That is a great idea to offer if they want help coming up with a password.
DanO