How to Check Last Password Change Date and Time for Domain Users in Active Directory

4

Managing password policies and tracking password changes is a critical aspect of enterprise security. As system administrators, we often need to verify when users last changed their passwords to ensure compliance with organizational security policies or troubleshoot authentication issues. This comprehensive guide explores multiple methods to retrieve last password change information for domain users in Active Directory.

Understanding Password Attributes in Active Directory

Before diving into the methods, it’s essential to understand the key Active Directory attributes related to password changes:

  • pwdLastSet: Stores the timestamp of the last password change as a Windows FILETIME value
  • PasswordLastSet: The PowerShell-friendly representation of pwdLastSet
  • LastLogonDate: Indicates when the user last authenticated (different from password change)
  • PasswordExpired: Boolean value indicating if the password has expired
  • PasswordNeverExpires: Boolean value indicating if the password is set to never expire

Method 1: Using PowerShell with Active Directory Module

PowerShell provides the most flexible and scriptable approach for retrieving password information. The Active Directory module offers cmdlets specifically designed for this purpose.

Prerequisites

  • Active Directory PowerShell module installed
  • Appropriate permissions to query AD user objects
  • Domain connectivity

Basic Query for Single User

# Import the Active Directory module
Import-Module ActiveDirectory

# Get password information for a specific user
$user = Get-ADUser -Identity "john.doe" -Properties PasswordLastSet, PasswordExpired, PasswordNeverExpires
Write-Host "User: $($user.Name)"
Write-Host "Last Password Change: $($user.PasswordLastSet)"
Write-Host "Password Expired: $($user.PasswordExpired)"
Write-Host "Password Never Expires: $($user.PasswordNeverExpires)"

Bulk Query for Multiple Users

# Get password information for all users in a specific OU
$users = Get-ADUser -SearchBase "OU=Users,DC=company,DC=com" -Filter * -Properties PasswordLastSet, PasswordExpired, PasswordNeverExpires

# Display results in a formatted table
$users | Select-Object Name, SamAccountName, PasswordLastSet, PasswordExpired, PasswordNeverExpires | Format-Table -AutoSize

Advanced Filtering and Reporting

# Find users who haven't changed passwords in the last 90 days
$cutoffDate = (Get-Date).AddDays(-90)
$stalePasswords = Get-ADUser -Filter * -Properties PasswordLastSet |
Where-Object { $_.PasswordLastSet -lt $cutoffDate -and $_.PasswordLastSet -ne $null } |
Select-Object Name, SamAccountName, PasswordLastSet

# Export to CSV for reporting
$stalePasswords | Export-Csv -Path "C:\Reports\StalePasswords.csv" -NoTypeInformation

Method 2: Using Command Line Tools

DSQUERY and DSGET Commands

For environments where PowerShell might not be available, traditional command-line tools can be used:

# Query user and get password last set information
dsquery user -name "John Doe" | dsget user -pwdlastset -display

NET USER Command (Limited Information)

# Basic user information including password details
net user john.doe /domain

Method 3: Using LDAP Queries

For more advanced scenarios or integration with custom applications, direct LDAP queries can be performed:

PowerShell LDAP Query

# Direct LDAP query for password information
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.Filter = "(&(objectClass=user)(sAMAccountName=john.doe))"
$searcher.PropertiesToLoad.Add("pwdLastSet") | Out-Null
$searcher.PropertiesToLoad.Add("name") | Out-Null

$result = $searcher.FindOne()
if ($result) {
$pwdLastSet = $result.Properties["pwdlastset"][0]
$passwordDate = [DateTime]::FromFileTime($pwdLastSet)
Write-Host "Password Last Set: $passwordDate"
}

Method 4: Using Active Directory Administrative Center (GUI)

For administrators who prefer graphical interfaces:

  1. Open Active Directory Administrative Center
  2. Navigate to the appropriate domain or OU
  3. Locate the target user account
  4. Right-click and select “Properties”
  5. Navigate to the “Account” tab
  6. View the “Password last set” field

Interpreting the Results

Understanding FILETIME Values

Active Directory stores timestamps as FILETIME values (64-bit integers representing 100-nanosecond intervals since January 1, 1601). PowerShell automatically converts these to readable DateTime objects.

Special Cases to Consider

  • Never Set Passwords: If pwdLastSet is 0, the password has never been set
  • Admin Reset: When an administrator resets a password, pwdLastSet updates to the reset time
  • System Accounts: Service accounts may show unexpected patterns based on their configuration

Best Practices and Security Considerations

Regular Monitoring

Implement automated scripts to regularly check password ages across your organization:

# Scheduled task script for password monitoring
$warningDays = 30
$criticalDays = 90
$warningDate = (Get-Date).AddDays(-$warningDays)
$criticalDate = (Get-Date).AddDays(-$criticalDays)

$users = Get-ADUser -Filter * -Properties PasswordLastSet | Where-Object { $_.Enabled -eq $true }

foreach ($user in $users) {
if ($user.PasswordLastSet -lt $criticalDate) {
Write-Warning "CRITICAL: $($user.Name) - Password age exceeds $criticalDays days"
} elseif ($user.PasswordLastSet -lt $warningDate) {
Write-Warning "WARNING: $($user.Name) - Password age exceeds $warningDays days"
}
}

Compliance Reporting

Create comprehensive reports for security audits and compliance requirements:

# Generate compliance report
$report = Get-ADUser -Filter * -Properties PasswordLastSet, PasswordExpired, PasswordNeverExpires, LastLogonDate |
Select-Object @{
Name = "Username"
Expression = { $_.SamAccountName }
}, @{
Name = "Display Name"
Expression = { $_.Name }
}, @{
Name = "Password Last Set"
Expression = { $_.PasswordLastSet }
}, @{
Name = "Days Since Password Change"
Expression = {
if ($_.PasswordLastSet) {
(New-TimeSpan -Start $_.PasswordLastSet -End (Get-Date)).Days
} else {
"Never Set"
}
}
}, @{
Name = "Password Expired"
Expression = { $_.PasswordExpired }
}, @{
Name = "Last Logon"
Expression = { $_.LastLogonDate }
}

$report | Export-Csv -Path "C:\Reports\PasswordCompliance.csv" -NoTypeInformation

Automation and Integration

PowerShell Modules and Functions

Create reusable functions for password checking:

function Get-PasswordAge {
param(
[Parameter(Mandatory=$true)]
[string]$Username
)

try {
$user = Get-ADUser -Identity $Username -Properties PasswordLastSet
if ($user.PasswordLastSet) {
$age = (New-TimeSpan -Start $user.PasswordLastSet -End (Get-Date)).Days
return [PSCustomObject]@{
Username = $Username
PasswordLastSet = $user.PasswordLastSet
PasswordAge = $age
}
} else {
return [PSCustomObject]@{
Username = $Username
PasswordLastSet = "Never Set"
PasswordAge = "N/A"
}
}
} catch {
Write-Error "Error retrieving password information for $Username: $($_.Exception.Message)"
}
}

Conclusion

Monitoring password change dates and times is crucial for maintaining security hygiene in Active Directory environments. Whether you prefer PowerShell automation, command-line tools, or graphical interfaces, Active Directory provides multiple methods to track this vital security information.

Regular monitoring, automated reporting, and proactive password policy enforcement help ensure your organization maintains strong security posture while meeting compliance requirements. By implementing the methods and best practices outlined in this guide, administrators can effectively manage and monitor password lifecycles across their domain infrastructure.

Remember to always test scripts in a non-production environment first and ensure you have appropriate permissions and backups before making any changes to Active Directory objects.

80%
Awesome
  • Design
Leave A Reply

Your email address will not be published.

Verified by MonsterInsights