How to create an Intelligent Password Policy for Active Directory

Shaun VermaakCOG Lead Engineer
CERTIFIED EXPERT
My name is Shaun Vermaak and I have always been fascinated with technology and how we use it to enhance our lives and business.
Published:
Updated:
Edited by: McKnife
This article documents the process of assigning different password policies based on user account password strength. The result of this script is that all the users that are using weak passwords are forced to have a password policy on them that allows their passwords to be valid for fewer days.

Introduction


Native password policy for Microsoft Active Directory is only good enough to implement the most basic password policy.


Typically companies opt for an 8 character complex password, but what people don't realize is that with such a policy, the following are perfectly acceptable 


Password1
Company1
Pass1word
...


What is disconcerting to me, is that without a third party password application (password filter) there is no way to prevent it. 


This method outlines my process to nudge users in the right direction.


Process


1) Create Password setting object with a shorter maximum age, I recommend less than 10 days.

https://blogs.technet.microsoft.com/canitpro/2013/05/29/step-by-step-enabling-and-using-fine-grained-password-policies-in-ad/


2) Use DSInternals to do a password audit using common weak passwords and compromised accounts.

    You can download it from https://www.dsinternals.com/en/downloads/ or install it with the following command

Install-Module DSInternals

DSInternals is a Powershell library created by Michael Grafnetter, an Identity & Security Premier Field Engineer (PFE) at Microsoft. It is an excellent library and should be part of your toolset if you have anything to do with security.


I have used it previously here: 


Please note that if you install this via the Install-Module cmdlet, you will get a warning "Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from
'PSGallery'?"


3) Clear the group that is assigned to Password Setting Object and add these violating accounts to it.

    In this article I use DG-WeakPasswords


Powershell Script


Import the DS Internals module

Import-Module DSInternals


Set the name of the group that was configured in the fine-grained password policy

$group = "DG-WeakPasswords"


Set the fully qualified domain name (FQDN) 

$domainFQDN = "contoso.com"


Set the distinguished name (DN)

$domainDN = "dc=contoso,dc=com"


Build an NT hash dictionary file from the password.txt text file. The password.txt file contains a list of weak password that should not be allowed in the Active Directory. Don't have a password list? Get one here: 

Get-Content $passwordFile | ConvertTo-SecureString -AsPlainText -Force | ConvertTo-NTHash | out-file $dictionaryFile


Get a collection object which contains all the accounts from Active Directory including their hashes

$accounts = Get-ADReplAccount -All -Server $domainFQDN



Optional: If you want to test your current password strength to get the crackable passwords, you can convert the object to a HashCatNT list with the command below and submit it on HashKiller.

$accounts | Format-Custom -View HashcatNT


For more information, see my How to extract hashes from IFM backup article https://www.experts-exchange.com/articles/29569/How-to-extract-hashes-from-IFM-backup.html



Test the quality of the passwords using the $dictionary object

$output = $accounts | Test-PasswordQuality -WeakPasswordHashes $dictionary -ShowPlainTextPasswords -IncludeDisabledAccounts


Clear the group. All user passwords need to be audited from scratch because some might have changed their passwords to a secure one

Get-ADGroupMember $group | ForEach-Object {Remove-ADGroupMember $group $_ -Confirm:$false}


Add all users that failed password audit to the group:

foreach($user in $output.WeakPassword) { Add-ADGroupMember -Identity $group -Members $user.Name}


Here's the complete script:

Import-Module DSInternals

$group = "WeakPasswords"
$domainFQDN = "contoso.com"
$domainDN = "DC=contoso,DC=com"
$dictionaryFile = ".\ntlmhashes.txt"
$passwordFile = ".\passwords.txt"

Get-Content $passwordFile | ConvertTo-SecureString -AsPlainText -Force | ConvertTo-NTHash | out-file $dictionaryFile

$accounts = Get-ADReplAccount -All -Server $domainFQDN

$output = $accounts | Test-PasswordQuality -WeakPasswordHashesfile $dictionaryFile -ShowPlainTextPasswords -IncludeDisabledAccounts

Get-ADGroupMember $group | ForEach-Object {Remove-ADGroupMember $group $_ -Confirm:$false}
foreach($user in $output.WeakPassword) { Add-ADGroupMember -Identity $group -Members $user.Name}


Conclusion


The result of this script is that the group will contain all the users that are using weak passwords. This forces a password policy - using fine-grained password policies - on them, that allows their passwords to be valid for fewer days than if they were to have specified a strong password




I hope you found this Powershell script useful, I guarantee that your password quality will drastically increase.


You are encouraged to ask questions, report any bugs or make any other comments about it below.

 

Note: If you need further "Support" about this topic, please consider using the Ask a Question feature of Experts Exchange. I monitor questions asked and would be pleased to provide any additional support required in questions asked in this manner, along with other EE experts...  

 

Don't forget to press the "Thumbs Up" button if you think this article was helpful


It also provides me with positive feedback. Thank you!

6
2,753 Views
Shaun VermaakCOG Lead Engineer
CERTIFIED EXPERT
My name is Shaun Vermaak and I have always been fascinated with technology and how we use it to enhance our lives and business.

Comments (3)

Albert WidjajaIT Professional
CERTIFIED EXPERT

Commented:
Hi Shaun,

Can the DSInternals module be installed in another computer without RSAT installed?
Because I wanted to run the scheduled task for this report to send out email alert, not from the Domain Controller.
Shaun VermaakCOG Lead Engineer
CERTIFIED EXPERT
Awarded 2017
Distinguished Expert 2019

Author

Commented:
Yes, it can :)

Just remember that you do not need DA. Configure an account with replicate directory access an use that in your scheduled task
CERTIFIED EXPERT
Distinguished Expert 2019

Commented:
In case anyone is trying to use it with the current version of DSInternals: it needs some changes to the syntax.

Import-Module DSInternals

$group = "WeakPasswords"
$domainFQDN = "contoso.com"
$domainDN = "DC=contoso,DC=com"
$dictionary = "c:\pwtest\ntlmhashes.txt"

Get-Content "C:\pwtest\passwords.txt" | ConvertTo-SecureString -AsPlainText -Force | ConvertTo-NTHash | out-file $dictionary
$accounts = Get-ADReplAccount -All -Server localhost
$output = $accounts | Test-PasswordQuality -WeakPasswordHashesfile $dictionary

Get-ADGroupMember $group | ForEach-Object {Remove-ADGroupMember $group $_ -Confirm:$false}
$Array =$output.WeakPassword.Split("\")
$weak=for ($i=1;$i -lt $Array.count;$i+=2) {$CharArray[$i]}
foreach ($user in $weak) {Add-ADGroupMember -Identity $group -Members $user}

Open in new window


I have tested this code on the DC itself, that's why I use "localhost" as servername.

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.