This does not actually analyse the actual password but more the metrics around the password which include:
- When the password was set?
- When the password expired?
- How old the password is?
Which will then display this in a table as below:
Script : PasswordMetrics.ps1
# Import required module
Import-Module ActiveDirectory
# Check if users.txt exists
if (!(Test-Path "users.txt")) {
Write-Host "Error: users.txt not found!" -ForegroundColor Red
exit
}
# Create an array to hold our results
$results = @()
# Process each user
Get-Content "users.txt" | ForEach-Object {
$user = Get-ADUser -Filter {UserPrincipalName -eq $_} -Properties PasswordLastSet, msDS-UserPasswordExpiryTimeComputed
if ($user) {
$passwordAge = if ($user.PasswordLastSet) {
((Get-Date) - $user.PasswordLastSet).Days
} else {
"N/A"
}
$expiryDate = [datetime]::FromFileTime($user.'msDS-UserPasswordExpiryTimeComputed')
$results += [PSCustomObject]@{
UPN = $_
'Password Set' = $user.PasswordLastSet
'Password Expires' = $expiryDate
'Password Age (Days)' = $passwordAge
}
} else {
$results += [PSCustomObject]@{
UPN = $_
'Password Set' = "Not Found"
'Password Expires' = "Not Found"
'Password Age (Days)' = "Not Found"
}
}
}
# Output the results in a formatted table
$results | Format-Table -AutoSize
Enhanced Details Report
If you need further details on the account in question then you can use the enhanced version of this script will will output a few more details as below, this version also saves the data to a CSV file:
Script : PasswordDetailed.ps1
Script : PasswordDetailed.ps1
# Import required module
Import-Module ActiveDirectory
# Check if users.txt exists
if (!(Test-Path "users.txt")) {
Write-Host "Error: users.txt not found!" -ForegroundColor Red
exit
}
# Create an array to hold our results
$results = @()
# Process each user
Get-Content "users.txt" | ForEach-Object {
$user = Get-ADUser -Filter {UserPrincipalName -eq $_} -Properties PasswordLastSet,
msDS-UserPasswordExpiryTimeComputed,
LastLogonDate,
PasswordNeverExpires,
LockedOut,
Enabled,
BadPwdCount,
LastBadPasswordAttempt,
PasswordExpired
if ($user) {
$passwordAge = if ($user.PasswordLastSet) {
((Get-Date) - $user.PasswordLastSet).Days
} else {
"N/A"
}
$expiryDate = if ($user.PasswordNeverExpires) {
"Never"
} else {
[datetime]::FromFileTime($user.'msDS-UserPasswordExpiryTimeComputed')
}
# Calculate days until expiry
$daysUntilExpiry = if ($expiryDate -eq "Never") {
"N/A"
} else {
((Get-Date $expiryDate) - (Get-Date)).Days
}
$results += [PSCustomObject]@{
UPN = $_
'Account Enabled' = $user.Enabled
'Password Set' = $user.PasswordLastSet
'Password Age (Days)' = $passwordAge
'Password Expires' = $expiryDate
'Days Until Expiry' = $daysUntilExpiry
'Password Never Expires' = $user.PasswordNeverExpires
'Password Expired' = $user.PasswordExpired
'Account Locked' = $user.LockedOut
'Bad Password Count' = $user.BadPwdCount
'Last Bad Password' = $user.LastBadPasswordAttempt
'Last Logon' = $user.LastLogonDate
}
} else {
$results += [PSCustomObject]@{
UPN = $_
'Account Enabled' = "Not Found"
'Password Set' = "Not Found"
'Password Age (Days)' = "Not Found"
'Password Expires' = "Not Found"
'Days Until Expiry' = "Not Found"
'Password Never Expires' = "Not Found"
'Password Expired' = "Not Found"
'Account Locked' = "Not Found"
'Bad Password Count' = "Not Found"
'Last Bad Password' = "Not Found"
'Last Logon' = "Not Found"
}
}
}
# Output the results in a formatted table
$results | Format-Table -AutoSize -Wrap
# Optionally export to CSV for better readability
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$results | Export-Csv -Path "PasswordReport_$timestamp.csv" -NoTypeInformation
Write-Host "`nReport also exported to: PasswordReport_$timestamp.csv" -ForegroundColor Green