If you’ve ever managed user accounts in Active Directory (AD), you have inevitably configured the password never expires flag on the account. The flag works exactly like the name implies: when set, your domain’s password expiration policy (and any applicable fine-grained password policy expiration settings) does not apply to the user. Many organizations have accumulated countless years of technical debt by setting this flag for service accounts without implementing a process to regularly rotate service account passwords. Sooner or later you will need to generate a list of accounts with this flag set and/or automate changing it in bulk.

When Should You Use Password Never Expires?
Historically, best practices indicated that user account passwords should be changed on a regular basis (e.g., every 90 days). Modern guidance says that this weakens security because it creates behaviors where end users choose passwords that are susceptible to password spray attacks. Service accounts should still have their password rotated on a regular (e.g., annual) basis. You can use the password never expires flag to manage this process, but not as an exception to rotating service account passwords. Service accounts with old passwords are susceptible to Kerberoasting attacks. An even better approach is to use a managed service account so that Windows handles the password change automatically.
Managing Password Expiry with PowerShell
Under the covers, AD keeps track of whether a user’s password should never expire by setting a bit on the userAccountControl attribute. Querying AD for a list of accounts that have this flag set is more complicated since you cannot filter on a specific attribute. Instead, you must construct a bitwise LDAP filter using the LDAP_MATCHING_RULE_BIT_AND operator. Fortunately, PowerShell makes this easier by abstracting the complexities of the LDAP filter.
Searching for Users
Partner with Microsoft experts you can trust
If it’s time to take that first step toward leveling up your organization’s security, get in touch with Ravenswood to start the conversation.
To retrieve a list of every user whose password never expires, you can run the following command:
Get-ADUser -Filter {PasswordNeverExpires -eq $true}
You can further filter this, for example, to include only users whose password never expires and whose password was last changed 180 days ago:
Get-ADUser -Filter {PasswordNeverExpires -eq $true} -Properties PasswordLastSet | Where {$_.PasswordLastSet -lt (Get-Date).AddDays(-180)}
Once you have a list of users, you can take action. Your action plan might involve resetting the passwords (in the case of service accounts) or clearing the password never expires flag.
Clearing the Password Never Expires Flag
Clearing the password never expires flag involves setting a bit in userAccountControl to 0 on the user object. PowerShell makes this easy by providing a switch parameter that you can use to toggle the bit. The simplest example below clears the password never expires flag for an individual user named Britta Simon:
Set-ADUser britta.simon -PasswordNeverExpires:$false
Chances are you will want to work with a list of users to perform this task in bulk. You can do that by piping the results of Get-ADUser to Set-ADUser, or by importing a list of users from a text file or CSV file. In the example below, we pass a list of users to Set-ADUser. In the sample text file, each line is a username:
$userList = Get-Content .\userList.txt
$userList | % { Set-ADUser $_ -PasswordNeverExpires:$false}
Be very careful performing bulk operations. Also keep in mind that if you have a password expiration policy (either at the domain level or in a fine grained password policy), when you clear the password never expires flag, the policy will immediately apply. If the user’s password age is older than the password expiration policy permits, they will be forced to change their password at their next logon. In the case of service accounts, this can cause an outage. The expiration date is calculated by adding the maximum password age setting to the user’s password last set timestamp. You can mitigate the risks of causing an outage by pre-emptively changing passwords so that they are no longer expired prior to clearing the password never expires flag.
Conclusion
By default, user passwords in AD expire according to the policies you have configured. You can exempt certain accounts from this by setting the password never expires bit in userAccountControl. This is a convenient way to exempt service accounts but it also can create security vulnerabilities. You should have a process in place to regularly rotate service account passwords and ensure that you are not using a weak password. PowerShell can be used to report on what accounts are set to have their password never expire and also to toggle the setting in bulk.
Managing password policies and service account security across your Active Directory environment? Contact Ravenswood Technology Group for expert assistance with credential management strategies and eliminating password-related security risks.