Hey there!
Hope you’re having a great week.
It's Cybersecurity Awareness Month, and there's no better time to audit one of your organization's most vulnerable attack surfaces: weak passwords.
You know they're out there. "Password123," "Summer2024," maybe even "CompanyName2025." These passwords are ticking time bombs in your Active Directory, and attackers know it.
Today, we're showing you how to identify weak passwords using PowerShell and the DSInternals module — before the bad guys do.
Why This Matters
You can't retrieve plain-text passwords from Active Directory (by design), but you can compare password hashes against known weak and breached password lists. The DSInternals module's Test-PasswordQuality
cmdlet does exactly that, scanning your AD environment for passwords that match common dictionaries or have been exposed in data breaches.
⚠️ Critical Warning: Test First, Deploy Second ⚠️
Before you run any script in production, always test in a lab or test environment first. Tools like DSInternals use techniques similar to DCSync attacks to replicate password hashes — and running them in production will light up your security monitoring tools like a Christmas tree.
Your SOC will see the alerts. Your SIEM will flag the activity. And if you haven't coordinated with your security team first, you might find yourself answering some uncomfortable questions.
Test safely. Communicate clearly. Deploy smartly.
Getting Started: Prerequisites
Before diving in, make sure you have:
DSInternals PowerShell module installed on a system with domain access (domain controller or management server):
Install-Module DSInternals -Force
A password dictionary containing known weak or breached passwords. Great sources include:
NCSC password lists
Have I Been Pwned (HIBP) databases
Or create your own notepad file with the known easy passwords. E.g. Password1, Welcome123 etc.
Step 1: Extract Password Hashes
You have two options:
Method 1: Online DCSync (most common)
Requires Domain Administrator privileges and replicates hashes directly from a domain controller:
$accounts = Get-ADReplAccount -All -Server "<DomainControllerName>"
Example 1: Retrieve all replication accounts from a domain controller
$accounts = Get-ADReplAccount -All -Server "DC01"
Example 2: Retrieve only a specific user account by SAM account name
Get-ADReplAccount -SamAccountName "jdoe" -Domain "contoso.com" -Server "DC02"
Example 3: Dump all accounts in a specific naming context
Get-ADReplAccount -All -NamingContext 'DC=contoso,DC=com' -Server "DC03"
Method 2: Offline Analysis
More stealthy — requires offline access to the ntds.dit
file:
$accounts = Get-ADDBAccount -DBPath "C:\Offline_ntds\ntds.dit"
Reads all account data from an offline AD backup file.
Step 2: Test Password Quality
Run the audit by piping your accounts into Test-PasswordQuality
:
powershell
$passwordQualityReport = $accounts | Test-PasswordQuality -WeakPasswordsFile "C:\Dictionaries\WeakPasswordDict.txt" -IncludeDisabledAccounts
This command checks for:
Weak dictionary passwords
Empty passwords
Duplicate passwords across users
Accounts with passwords that never expire
Accounts with reversible encryption enabled
Step 3: Analyze the Results
View accounts with weak passwords:
$passwordQualityReport.WeakPassword | Format-Table SamAccountName, DisplayName, Sid
Check for duplicate passwords:
$passwordQualityReport.DuplicatePassword | Format-Table *
Step 4: Export and Remediate
Export the findings to a CSV for reporting:
$passwordQualityReport.WeakPassword | Export-Csv -Path "C:\Reports\WeakPasswords.csv" -NoTypeInformation
Optionally, force password resets for affected users:
Import-Csv -Path "C:\Reports\WeakPasswords.csv" | ForEach-Object {
Set-ADUser -Identity $_.SamAccountName -ChangePasswordAtLogon $true
Write-Host "Forced password reset for user: $($_.SamAccountName)"
}
Ready-to-Use Script
Here's a complete script to get you started (remember: test environment first!):
# --- Configuration ---
$DomainController = "your_domain_controller_name"
$PasswordDictionaryPath = "C:\Dictionaries\WeakPasswordDict.txt"
$ExportFilePath = "C:\Reports\WeakPasswords.csv"
# --- Prerequisite check ---
if (-not (Get-Module -ListAvailable -Name DSInternals)) {
Write-Host "DSInternals module not found. Installing now..."
Install-Module DSInternals -Force
}
# --- Password audit ---
Write-Host "Retrieving Active Directory user password hashes via DCSync..."
try {
$accounts = Get-ADReplAccount -All -Server $DomainController
}
catch {
Write-Error "Failed to retrieve account data. Ensure you have Domain Administrator privileges."
return
}
if (-not (Test-Path $PasswordDictionaryPath)) {
Write-Error "Password dictionary file not found at: $PasswordDictionaryPath"
return
}
Write-Host "Testing password quality against the weak password dictionary..."
$passwordQualityReport = $accounts | Test-PasswordQuality -WeakPasswordsFile $PasswordDictionaryPath -IncludeDisabledAccounts
# --- Report and remediation ---
$weakPasswords = $passwordQualityReport.WeakPassword
if ($weakPasswords) {
Write-Warning "Weak passwords found for the following users:"
$weakPasswords | Format-Table SamAccountName, DisplayName, Sid
$weakPasswords | Export-Csv -Path $ExportFilePath -NoTypeInformation
Write-Host "Weak password report exported to $ExportFilePath"
}
else {
Write-Host "No weak passwords were identified based on the provided dictionary."
}
The Bottom Line
Weak passwords are low-hanging fruit for attackers. This Cybersecurity Awareness Month, take the time to audit your Active Directory and close this vulnerability before someone else exploits it.
And remember: always test in a safe environment first. Your security team (and your career) will thank you.
Found this helpful? Forward this newsletter to your fellow IT professionals and sysadmins. The more teams auditing their passwords this month, the harder we make it for attackers everywhere.
Have you run a password audit in your environment? What surprised you most about the results? Share your experience in the comments.