Would you like to
- detect if service accounts or admins are re-using same passwords in Active Directory
- detect if any accounts are using company standard passwords, based on a dictionary (TXT-file you can provide)
- detect if sensitive accounts are using passwords, previously being hacked and found on HaveIBeenPwned
- detect users with no password set
- detect users with same passwords
- detect accounts that are susceptible to the Kerberoasting attack
- detect administrative accounts that are allowed to be delegated to a service
- detect accounts where Kerberos pre-authentication is not required
- detect accounts where Kerberos AES keys are missing
- detect computer accounts having default passwords
- detect accounts with ‘passwords will never expire’
- detect accounts that are not required to have a password
If yes, then continue on reading this blog-post 🙂
Great job Michael Grafnetter
Initially, I would like to thank the author of DSInternals, Microsoft MVP Michael Grafnetter, for creating the amazing powershell module, DSInternals. This is a rockstar tool !!
What is DSInternals ?
The DSInternals project consists of these two parts:
- The DSInternals Framework exposes several internal features of Active Directory and can be used from any .NET application.
- The DSInternals PowerShell Module provides easy-to-use cmdlets that are built on top of the Framework. These are the main features:
- Azure Active Directory FIDO2 key auditing and retrieval of system information about all user-registered key credentials.
- Active Directory password auditing that discovers accounts sharing the same passwords or having passwords in a public database like HaveIBeenPwned or in a custom dictionary.
- Key credential auditing and generation, including support for NGC, FIDO2 and STK keys. Keys can also be tested against the ROCA vulnerability. New NGC keys can also be registered through the MS-DRSR protocol.
- Bare-metal recovery of domain controllers from just IFM backups (ntds.dit + SYSVOL).
- Offline ntds.dit file manipulation, including hash dumping, password resets, group membership changes, SID History injection and enabling/disabling accounts.
- Online password hash dumping through the Directory Replication Service (DRS) Remote Protocol (MS-DRSR). This feature is commonly called DCSync.
- Domain or local account password hash injection through the Security Account Manager (SAM) Remote Protocol (MS-SAMR) or directly into the database.
- LSA Policy modification through the Local Security Authority (Domain Policy) Remote Protocol (MS-LSAD / LSARPC).
- Extracting credential roaming data and DPAPI domain backup keys, either online through directory replication, LSARPC and offline from ntds.dit.
- Password hash calculation, including NT hash, LM hash and kerberos keys.
How I use it for Password Auditing?
I use DSInternals for Password auditing to :
- detect if service accounts or admins are re-using same passwords. They must have an unique password
- detect if any accounts are using company standard passwords, based on a dictionary (TXT-file you can provide)
- detect if sensitive accounts are using passwords, previously being hacked and found on HaveIBeenPwned
- detect users with no password set
- detect users with same passwords
- detect accounts that are susceptible to the Kerberoasting attack
- detect administrative accounts that are allowed to be delegated to a service
- detect accounts where Kerberos pre-authentication is not required
- detect accounts where Kerberos AES keys are missing
- detect computer accounts having default passwords
- detect accounts with ‘passwords will never expire’
- detect accounts that are not required to have a password
I have uploaded my script on my github, where you can see how I use the tool for password auditing.
Script (main program)
#--------------------------------------------------------
# Variables
#--------------------------------------------------------
$PathOutput = "D:\Scripts\Output"
# This is the location where your password dictionary file exists. You can start by creating a simple file with one line like Password1234
$Passwords = "D:\SCRIPTS\DATA\AD-DictionaryPasswords.txt"
#------------------------------------------------------------------------------------------------------------
# MAIN PROGRAM
#------------------------------------------------------------------------------------------------------------
$ExportDateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$OutPutReport_ALL = "$($PathOutput)\OUTPUT\AD-PasswordQualityReport_ALL_$($ExportDateTime).txt"
$OutPutReport_Enabled_Only_ALL = "$($PathOutput)\OUTPUT\AD-PasswordQualityReport_Enabled_Only_ALL_$($ExportDateTime).txt"
$OutPutReport_Disabled_Only_ALL = "$($PathOutput)\OUTPUT\AD-PasswordQualityReport_Disabled_Only_ALL_$($ExportDateTime).txt"
$OutPutReport_Admins_Only_ALL = "$($PathOutput)\OUTPUT\AD-PasswordQualityReport_Admins_Only_ALL_$($ExportDateTime).txt"
$Result_ALL = Get-ADReplAccount -All:$true -Server (Get-ADDomainController).Hostname -NamingContext (Get-ADRootDSE | select *naming*).defaultNamingContext
$Result_Enabled_Only_ALL = $Result_ALL | Where-Object { ($_.Enabled -eq $true) -and ($_.SamAccountType -eq "User") }
$Result_Disabled_Only_ALL = $Result_ALL | Where-Object { ($_.Enabled -eq $false) -and ($_.SamAccountType -eq "User")}
$Result_Admins_Only_ALL = $Result_ALL | Where-Object { ($_.AdminCount -eq $true) -and ($_.SamAccountType -eq "User")}
$PasswordResult_All = $Result_ALL | Test-PasswordQuality -WeakPasswordsFile $Passwords
$PasswordResult_Enabled_Only_ALL = $Result_Enabled_Only_ALL | Test-PasswordQuality -WeakPasswordsFile $Passwords
$PasswordResult_Disabled_Only_ALL = $Result_Disabled_Only_ALL | Test-PasswordQuality -WeakPasswordsFile $Passwords
$PasswordResult_Admins_Only_ALL = $Result_Admins_Only_ALL | Test-PasswordQuality -WeakPasswordsFile $Passwords
Write-Output "Building reports ...."
$PasswordResult_All | Out-File -FilePath $OutPutReport_ALL -Encoding UTF8
$PasswordResult_Enabled_Only_ALL | Out-File -FilePath $OutPutReport_Enabled_Only_ALL -Encoding UTF8
$PasswordResult_Disabled_Only_ALL | Out-File -FilePath $OutPutReport_Disabled_Only_ALL -Encoding UTF8
$PasswordResult_Admins_Only_ALL | Out-File -FilePath $OutPutReport_Admins_Only_ALL -Encoding UTF8
Tip – adding OU-filtering
Get-ADReplAccount -All -Server 'dcsrv01.contoso.com' |
Where-Object DistinguishedName -like '*,OU=Admins,DC=contoso,DC=com' |
Test-PasswordQuality -WeakPasswordHashesSortedFile d:\scripts\data\ad-passwords.txt
Output
Active Directory Password Quality Report
----------------------------------------
Passwords of these accounts are stored using reversible encryption:
LM hashes of passwords of these accounts are present:
These accounts have no password set:
Passwords of these accounts have been found in the dictionary:
These groups of accounts have the same passwords:
Group 1:
xxxxx
yyyyy
Group 2:
xxxxx
yyyyy
These computer accounts have default passwords:
Kerberos AES keys are missing from these accounts:
Kerberos pre-authentication is not required for these accounts:
Only DES encryption is allowed to be used with these accounts:
These accounts are susceptible to the Kerberoasting attack:
xxxxx
yyyyy
These administrative accounts are allowed to be delegated to a service:
xxxxx
yyyyy
Passwords of these accounts will never expire:
xxxxx
yyyyy
These accounts are not required to have a password:
These accounts that require smart card authentication have a password:
Prerequisites before running the script
Microsoft Defender for Identity Exclusions
In case your environment is monitoring by Microsoft Defender for Identity, please start by making an exception of the machine, from where you run the scripts. Otherwise you will get an alert with ‘Suspected DCSync attack (replication of directory services)’

Creation of company dictionary password file
Create a text-file with any known company passwords, one line per password (sample below)
Password2020
Password2021
Password2022
Installation of Powershell module, DSInternals
# TLS 1.2 must be enabled on older versions of Windows.
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# Download the NuGet package manager binary.
Install-PackageProvider -Name NuGet -Force
# Register the PowerShell Gallery as package repository if it is missing for any reason.
if($null -eq (Get-PSRepository -Name PSGallery -ErrorAction SilentlyContinue)) { Register-PSRepository -Default }
# Download the DSInternals PowerShell module.
Install-Module -Name DSInternals -Force
More information
Please check out the official DSInternal homepage using this link
Here you can find other great blog-posts of how to use the other features.