Audit your Active Directory user passwords against haveibeenpwned.com safely using PowerShell
You will be surprised how many of your users are on the list :)
In this article, I will show you, how to easily and securely check, whether some of your users are using leaked passwords. All of this by running one PowerShell function ๐.
Why you should care you may ask? Leaked passwords shouldn't be used, because attackers will with high probability try to use them in their brute force attacks (like in last Colonial Pipeline attack). Plus attackers are in general exploiting human laziness i.e. usage of the same password across different services.
What does it mean securely? There are free tools or builtin paid one that do quite the same thing as my solution. But when dealing with AD passwords (or generally anything that needs Domain Admin rights) I am very cautious. Therefore I do all sensitive actions in VM without a network connection, use secure delete, plus data never leaves high tier servers. So no sensitive information can leak.
Disclaimer
What is safe in my environment can be unsafe in yours, so think this through before implementing!
Table of Contents
Prerequisites:
- Domain Admin rights, for extracting user password hashes from your DC
- Hyper-V server cluster managed by SCVMM, for hosting VM without network connectivity (as a safe playground that cannot leak any sensitive information)
- (you can just extract the interesting parts from my function and use them as you wish)
- PowerShell for automation and Powershell Direct for controlling VM
- Downloaded database of leaked NTLM hashes from haveibeenpwned.com, for comparison with your user hashes
- Awesome DSInternals PowerShell module, for comparing passwords from your AD against the downloaded database
Break down of the PowerShell function
Function Invoke-ADPasswordsAudit will:
- Check if there is a newer version of haveibeenpwnd database
- Export ntds.dit and syskey on random DC
- Creates VM on Hyper-V cluster node (without network connection)
- To cluster node, where VM will be hosted copy
- exported ntds and syskey
- DSInternals and haveibeenpwnd database
- Delete ntds.dit and syskey on DC
- From cluster node to VM copy
- exported ntds and syskey
- DSInternals and haveibeenpwnd database
- Delete this copied data on the cluster node
- ntds.dit and syskey
- deprecated haveibeenpwnd databases
- Run DSInternals function Test-PasswordQuality inside the VM, to test AD passwords
- Get the results
- Remove VM
Interesting parts of the function
1. Extracting Active Directory passwords
"Exporting NTDS and syskey on $DC"
# where the exported data will be stored on DC
$IFMPath = "C:\Windows\whatever"
# pick DC with PDCEmulator role (it doesn't matter, but why not)
$DC = ((Get-ADDomain | Select-Object -exp PDCEmulator) -split "\.")[0]
Invoke-Command -ComputerName $DC {
param ($IFMPath)
if (Test-Path $IFMPath -ea SilentlyContinue) { Remove-Item $IFMPath -Recurse -Force }
$IFM = ntdsutil "activate instance ntds" ifm "create full `"$IFMPath`"" q q
if (!($IFM -like "*IFM media created successfully*")) {
Remove-Item $IFMPath -Recurse -Force # just for sure
throw "Export failed`n`n$IFM"
}
} -ArgumentList $IFMPath
2. Running DSInternals with haveibeenpwned database against extracted passwords
Just for sure, on VM without network connection run:
"Getting leaked passwords used in your Active Directory domain"
Import-Module "DSinternals" -ErrorAction Stop
#region important variables
# path to downloaded ntlm ordered database of passwords from https://haveibeenpwned.com/Passwords
$pwnedPasswords = "C:\whatever\pwned-passwords-ntlm-ordered-by-hash.txt"
# path to txt file with manually entered passwords you want to check too (one password at a line)
$weakPasswords = "C:\whatever\weakPasswordsFile.txt"
# path to exported SYSTEM registry that you've got on DC by running ntdsutil command in previous step
$key = Get-BootKey -SystemHivePath 'C:\whatever\registry\SYSTEM'
if (!$key) { throw "Couldn't get syskey" }
# path to exported ntds.dit password database that you've got on DC by running ntdsutil command in previous step
$ntds = 'C:\whatever\Active Directory\ntds.dit'
#endregion important variables
# parameters for Test-PasswordQuality
$params = @{
WeakPasswordHashesSortedFile = $pwnedPasswords
}
if ($weakPasswords) {
$params.WeakPasswordsFile = $weakPasswords
}
# run passwords audit
$result = Get-ADDBAccount -All -DatabasePath $ntds -BootKey $key | Test-PasswordQuality @params
# to get nice human readable output
return ($result | Out-String)
OK so how to use it?
- To
C:\ADAudit
download:- DSInternals module
mkdir C:\ADAudit Save-Module DSInternals C:\ADAudit
- Newest NTLM ordered passwords file
- Both PowerShell scripts ( Invoke-ADPasswordsAudit, New-VMFromTemplate)
- DSInternals module
- Check the content of both scripts to know, what they are doing
- Test & modify the
New-VMFromTemplate
function to work in your environment - In PowerShell console that runs under Domain Admin
- Dot source both scripts to load defined functions
- Run
Invoke-ADPasswordsAudit -pwnedPasswordsNTLMOrdered "C:\ADAudit\pwned-passwords-ntlm-ordered-by-hash-v7.txt" -DSInternals "C:\ADAudit\DSInternals"
- Wait :)
- It can take dozens of minutes to finish because a new VM has to be created, 20GB passwords file has to be copied to node cluster and then to VM itself, and of course, your AD hashes has to be compared with it...
Summary
It's good practice to run this function on regular basis, because passwords of your users are going to change, so as leaked password database :)
Enjoy! ๐