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 disconcerning 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.
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:
- Password Synchronization from one Active Directory Domain to another using DSInternals
- How to extract hashes from IFM backup
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:
- https://wpengine.com/unmasked/(Good information, some of the links are broken)
- https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt
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://ittelligence.blog/2017/05/16/extract-hashes-ifm-backup/
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
