Tutorials › PowerShell

Find and fix 'password never expires' accounts with PowerShell

"Password never expires" is often ticked to make a problem go away and then forgotten. On an admin account it means one leaked password could work for years. This tutorial uses PowerShell to find these accounts, check them, and switch the setting off safely, with a dry run first.

Before you start

  • You need an account that can modify users in Active Directory, and the Active Directory module for PowerShell. It is installed on domain controllers, and on other machines with the RSAT Active Directory tools.
  • Agree with the account owners what should happen. Some service accounts have this ticked on purpose, and changing them without a plan can stop an application.
  • Have a list of your break-glass and service accounts to hand.

Steps

  1. Sign in to a domain controller or a management server with RSAT installed.
  2. Right-click Start and select Terminal (Admin) or Windows PowerShell (Admin).
  3. Load the module:
    Import-Module ActiveDirectory
  4. Check your domain's maximum password age. You'll need it in step 9:
    Get-ADDefaultDomainPasswordPolicy | Select-Object MaxPasswordAge
  5. List every enabled user with the setting turned on, oldest password first:
    Get-ADUser -Filter 'PasswordNeverExpires -eq $true -and Enabled -eq $true' -Properties PasswordNeverExpires, PasswordLastSet, LastLogonDate |
        Select-Object Name, SamAccountName, PasswordLastSet, LastLogonDate, DistinguishedName |
        Sort-Object PasswordLastSet
  6. Look at privileged accounts first. Accounts with AdminCount set to 1 are, or have been, in a protected admin group. Microsoft's own example uses this filter:
    Get-ADUser -Filter {(AdminCount -eq 1) -and (PasswordNeverExpires -eq $true)} |
        Select-Object Name, SamAccountName
    A human admin account in this list is the thing to fix first.
  7. Export the full list so you have a record and can get sign-off:
    Get-ADUser -Filter 'PasswordNeverExpires -eq $true -and Enabled -eq $true' -Properties PasswordNeverExpires, PasswordLastSet, LastLogonDate, AdminCount |
        Select-Object Name, SamAccountName, PasswordLastSet, LastLogonDate, AdminCount, DistinguishedName |
        Export-Csv C:\Temp\password-never-expires.csv -NoTypeInformation
    Create C:\Temp first if it doesn't exist.
  8. Open the CSV in Excel. Remove every service account, break-glass account and anything you don't recognise. Save what's left as C:\Temp\to-fix.csv, keeping the SamAccountName column.
  9. Compare each PasswordLastSet date with the maximum password age from step 4. If a password is older than that, the user will have to change it as soon as the flag is removed. Tell those users first, and check they're in the office or can reach self-service password reset.
    Removing the flag from an account with an old password can lock a user, or an application using that account, out straight away. Never run step 11 against service accounts without the application owner on board.
  10. Do a dry run. -WhatIf shows what would change without changing anything:
    Import-Csv C:\Temp\to-fix.csv | ForEach-Object {
        Set-ADUser -Identity $_.SamAccountName -PasswordNeverExpires $false -WhatIf
    }
    Read the output and check every name is one you expect.
  11. When you're happy, run it for real by removing -WhatIf:
    Import-Csv C:\Temp\to-fix.csv | ForEach-Object {
        Set-ADUser -Identity $_.SamAccountName -PasswordNeverExpires $false
    }
  12. To limit a change to one OU instead of using a CSV, use -SearchBase, as in Microsoft's Q&A example. It includes OUs nested underneath:
    Get-ADUser -Filter 'PasswordNeverExpires -eq $true' -SearchBase "OU=Staff,DC=contoso,DC=local" |
        Set-ADUser -PasswordNeverExpires $false -WhatIf

Check it worked

  1. Run the search again for the accounts you changed. It should return nothing:
    Import-Csv C:\Temp\to-fix.csv | ForEach-Object {
        Get-ADUser -Identity $_.SamAccountName -Properties PasswordNeverExpires |
            Select-Object SamAccountName, PasswordNeverExpires
    }
    Every line should show False.
  2. In Active Directory Users and Computers, open one of the users, go to the Account tab and check Password never expires is no longer ticked.
  3. Keep the CSV from step 7 with your change notes so you can show what was changed and when.
For service accounts that can't have expiring passwords, look at moving them to group managed service accounts (gMSA) over time. Windows changes those passwords for you.

Sources

← All tutorials