The Strange Case of Unenforced Password Complexity

Hello everyone, David Everett and Scott Goad here to discuss a recent issue that we thought you might find interesting. We were working with a customer that was trying to implement password complexity, but they were not seeing the behavior that we would normally expect.

The issue came about when trying to apply password complexity requirements, and having existing users change their password. This should force the complexity at password change, but in this customer’s case, complexity was not being enforced. Looking into the issue further, we tested with a new user account we created in DSA.MSC and noticed that password complexity worked as expected.

Lab time! We tested the password complexity requirements and started to look at one of the problem users. We were able to compare an LDIFDE dump, of the problem user with one taken from our lab that was not having the issue. At first glance, nothing looked awry, but digging deeper, we soon realized that the displayName attribute was not populated in the LDIFDE dump.

We investigated as to how the user accounts were provisioned, to better understand why this attribute was missing. The user accounts were created using SUN Identity Manager and then sync’d to Active Directory.

Why does this matter? Password complexity evaluates the sAMAccountName and displayName attributes and builds “tokens” that are used to check the password that is being presented against complexity requirements. These two attributes, in combination or separately, are used to build the tokens which are compared against the password that the user enters. In this case, having an empty displayName attribute caused password complexity to be relaxed. The policy was in place and working as expected, since it was still evaluating the sAMAccountName. Here is a sample of what you can see in the LDIFDE dump:

dn: CN=Test User 1,OU=staff,DC=top,DC=contoso,DC=com
changetype: add
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Test User 1
sn: User
givenName: Test
distinguishedName: CN=Test User 1,OU=staff,DC=top,DC=contoso,DC=com
instanceType: 4
whenCreated: 20060817140027.0Z
whenChanged: 20090518142050.0Z
uSNCreated: 693960
uSNChanged: 12104216
name: Test User 1
objectGUID:: a2dz2ugl0xGQeQCAXzH4Jg==
userAccountControl: 512
badPwdCount: 0
codePage: 0
countryCode: 0
homeDrive: U:
badPasswordTime: 128856853740701244
lastLogoff: 0
lastLogon: 128856853892263744
pwdLastSet: 128871300501924190
primaryGroupID: 513
accountExpires: 9223372036854775807
logonCount: 1
sAMAccountName: t_tUser
sAMAccountType: 805306368
userPrincipalName: t_tUser@top.contoso.com
lockoutTime: 0
objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=top,DC=contoso,DC=com

Based on this LDIFDE dump the only “token” that was being monitored for complexity was t_tUser in the sAMAccountName attribute. The admin was able to pass Test and User in the password. When password complexity is enforced, displayName and sAMAccountName attributes are checked. The new password is checked for “tokens”. It is important to note that a “token” must be three or more characters in length. Even then, only the whole “token” is used in the complexity check, not portions of the tokens. This comes into play when trying to evaluate tokens against displayName.

At this point, password complexity is being enforced as designed, but not what we would expect to see based on the user’s account information. The action plan that was provided to the customer was to populate the displayName attribute and test. This worked in testing, but ultimately the customer had to work with their vendor to resolve the issue with the sync process, allowing the displayName attribute to be populated from the SUN Identity Manager to Active Directory.

For more info on Password Complexity rules, see the recent blog post Understanding Password Policies.

- David Everett and Scott Goad, the Wonder Twins