Auditing Active Directory passwords against HaveIBeenPwned

Andrea Dainese
February 08, 2022
Post cover

Any password policy, even with strict rules, can be easily bypassed with simple tricks: Passw0rd!, Passw0rd$, Password!1 can be all valid passwords for length and complexity.

In this common scenario it’s useful to regularly audit Active Directory passwords against password dictionaries (like RockYou) and/or HaveIBeenPwned .

Let’s see how to audit Active Directory passwords using Directory Services Internals PowerShell Module and Framework .

Install

Open PowerShell with administrative privileges and check PowerShell version:

PS C:\Windows\system32> $PSVersionTable

$PSVersionTable must be 5.1 at least.

Install DSInternals:

PS C:\Windows\system32> Install-Module DSInternals -Force

If you got the error PackageManagement\Install-PackageProvider : No match was found for the specified search criteria for the provider 'NuGet'. The package provider requires 'PackageManagement' and 'Provider' tags, modify the security protocols (default is Ssl3 and Tls), and reinstall:

PS C:\Windows\system32> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
PS C:\Windows\system32> $PSVersionTable

List available cmdlets:

PS C:\Windows\system32> Get-Command -Module DSInternals*

Find weak passwords on a Domain Controller

Before we start the audit process, we need at least one dictionary file. Download any wordlist .

Set environment:

$DictFile = "C:\Users\Administrator\Downloads\rockyou.txt"
$DC = "dc01"
$Domain = "DC=example,DC=com"

Start the audit:

Get-ADReplAccount -All -Server $DC -NamingContext $Domain | Test-PasswordQuality -WeakPasswordsFile $DictFile -IncludeDisabledAccounts

We can also build a report in CSV format:

PS C:\Users\Administrator> $Accounts = Get-ADReplAccount -All -Server $DC -NamingContext $Domain
PS C:\Users\Administrator> $Results = $Accounts | Test-PasswordQuality -WeakPasswordsFile $DictFile
PS C:\Users\Administrator> $RiskyAccounts = $Accounts | where {$Results.WeakPassword -match $_.SamAccountName}
PS C:\Users\Administrator> $RiskyAccounts | select SamAccountName,DisplayName,DistinguishedName | Export-Csv output.csv

Mind that there are no built-in tools to set the list of bad passwords for Active Directory Domain Services.

Export data for a remote audit

At this moment, DSInternals cannot serialize accounts. See the associated issue .

Once it’s fixed, the procedure should be as follows.

PS C:\Users\andrea> $Password = Read-Host "Enter password (16 chars)" -AsSecureString
PS C:\Users\andrea> $Accounts = Get-ADReplAccount -All -Server $DC -NamingContext $Domain
PS C:\Users\andrea> $SerialAccounts = [System.Management.Automation.PSSerializer]::Serialize($Accounts)
PS C:\Users\andrea> $SerialAccounts | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString -SecureKey $Password | Set-Content -Path credentials.txt

Move the file to an external station with PowerShell 7 and get the data back:

PS C:\Users\andrea> $Password = Read-Host "Enter password (16 chars)" -AsSecureString
PS C:\Users\andrea> $SerialAccounts = Get-Content -Path credentials.txt | ConvertTo-SecureString -SecureKey $Password | ConvertFrom-SecureString -AsPlainText
PS C:\Users\andrea> $Accounts = [System.Management.Automation.PSSerializer]::DeSerialize($SerialAccounts)

Analyze the data as we did previously:

$DictFile = "C:\Users\andrea\Downloads\rockyou.txt"
$DC = "dc01"
$Domain = "DC=example,DC=com"
PS C:\Users\Administrator> $Results = $Accounts | Test-PasswordQuality -WeakPasswordsFile $DictFile
PS C:\Users\Administrator> $RiskyAccounts = $Accounts | where {$Results.WeakPassword -match $_.SamAccountName}
PS C:\Users\Administrator> $RiskyAccounts | select SamAccountName,DisplayName,DistinguishedName | Export-Csv output.csv

Check for breached credentials (HaveIBeenPwned)

I’m used to testing if users are using leaked passwords. To do that, download the password list from HaveIBeenPwned , and use the ordered by hash NTLM file.

Analyze the weak passwords using the downloaded file:

PS C:\Users\Administrator\Downloads> $Accounts | Test-PasswordQuality -WeakPasswordHashesSortedFile .\pwned-passwords-ntlm-ordered-by-hash-v8.txt
PS C:\Users\Administrator> $RiskyAccounts = $Accounts | where {$Results.WeakPassword -match $_.SamAccountName}
PS C:\Users\Administrator> $RiskyAccounts | select SamAccountName,DisplayName,DistinguishedName | Export-Csv output.csv

Next steps

Each account with a weak password should be forced to change the password at the next login. The user should also be notified via email. According to the organization’s policies, this could count as a security incident.

References

References