Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex that validates Active Directory default password complexity

I have a list of passwords that I need to examine and determine if they meet the default 3 of 4 rule for AD.

Rule is contain 3 of the 4 following requirements: lower case character (a-z) upper case character (A-Z) numeric (0-9) special character ( !@#$%^&*()_+= )

I am still learning Regex. I know how to select only those that meet any one character case, but I am not sure how to do 3 of 4.

As a side note, the AD Complexity has two more subtleties that are important (but out of scope of the original question).

It is really 3 of 5. The fifth is Unicode character. Be nice to update the Regex with that.

The other is you cannot have the sAMAccountName value in whole in the password (case insensitive), nor if you split the displayName value into tokens split upon space, comma, dash, underscore, pound, pipe and something else those tokens (3 chars and longer) cannot be in whole in the password, case insensitive.

like image 795
geoffc Avatar asked Apr 21 '09 20:04

geoffc


3 Answers

If you really want one big regex it would be something like this:

(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*

Note that it also enforces password length to be between 8 and 255 characters. You can change the "{8,255}" portion in the first section to adjust the length requirements. It is also worth noting that this is working for me in a standard ASP.NET RegularExpressionValidator control.

Matches: "Passw0rd" "passW@rd" "1B2a345@#$%"

Non-Matches: "123123123" "Password" "asdf&"

Source (Matthew Hazzard via RegExLib.com)

like image 175
Saul Dolgin Avatar answered Oct 18 '22 03:10

Saul Dolgin


Does it have to be all one big regex? You could do 4 regexes, each checking one thing and then make sure 3 of the 4 are matches. That would be easier, less error prone and more maintainable.

like image 26
JP Alioto Avatar answered Oct 18 '22 04:10

JP Alioto


You will have to build up the regular expression like this:

rule = [ "[a-z]", "[A-Z]", "[0-9]", "[!@#$%\^\&\(\)\+=]" ]

regex = ""
first = true
for a in 0..3:
  for b in 0..3:
    if a == b: continue
    for c in 0..3:
      if a == c or b == c: continue
      if not first:
        regex += "|"
      regex += "(" + rule[a] + ".*" + rule[b] + ".*" + rule[c] + ")"
      first = false

I'm not sure if I escaped the special characters correctly. It's kind of dependant on the language/toolkit you're using.

like image 30
moinudin Avatar answered Oct 18 '22 04:10

moinudin