Powershell : Analysing User Password Data

This does not actually analyse the actual password but more the metrics around the password which include:

  1. When the password was set?
  2. When the password expired?
  3. How old the password is?

Which will then display this in a table as below:

The usernames are taken from a file called users.txt and that file is ingested and then the UPN entries are analysed using the script 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

# 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

Previous Post Next Post

نموذج الاتصال