Last Update: Sep 04, 2024 | Published: Sep 29, 2014
In this Ask the Admin, I’ll show you how to audit Active Directory for accounts that have passwords set to never expire. Although it’s possible to configure policy in Active Directory (AD) to require a minimum password length, complexity, and to set how often passwords should be changed, AD should also be regularly audited for accounts that have passwords set to never expire, especially if they have administrative privileges to the domain or workstations.
The easiest way to audit Active Directory is to use PowerShell’s search-adaccount cmdlet. It’s only supported on Windows Server 2012 and Windows 8 (or later), so you should perform the instructions below on a Windows 8.1 management workstation with the Remote Server Administration Tools (RSAT) installed, or on a Windows Server 2012 R2 domain controller (DC).
search-adaccount –passwordneverexpires
The built-in guest account in Active Directory is disabled by default and has its account password set to never expire, so you are likely to see guest listed in the results. We can pipe the results of search-adaccount to the where-object cmdlet to show only accounts that are currently enabled.
search-adaccount –passwordneverexpires | where {$_.enabled}
You can also select the fields shown in the results using format-table as shown here:
search-adaccount –passwordneverexpires | where {$_.enabled} | format-table name,objectclass
Accounts that are disabled can be ignored, so the ability to see the results only for enabled accounts is valuable. I can make the results more useful by piping the output to PowerShell’s grid view, giving an Excel like display where the search results are organized into columns.
search-adaccount –passwordneverexpires | where {$_.enabled} | out-gridview
If you want to limit the fields in out-gridview, you’ll need to use the select-object cmdlet instead of format-table as shown here:
search-adaccount –passwordneverexpires | where {$_.enabled} | select-object name,objectclass | out-gridview
OK, well not quite. But if your Active Directory is carefully managed, you might decide to disable all enabled accounts that have passwords set to never expire. That’s easily achieved using PowerShell. Note that I’ve added the –usersonly parameter to the search-adaccount cmdlet to avoid disabling any other kind of account accidently.
search-adaccount –passwordneverexpires -usersonly | where {$_.enabled} | disable-adaccount
To further reduce the risk of automating the process of disabling accounts, you could also limit the search command to a specific Organizational Unit (OU) or container. In the example below, I’ve added the –searchbase parameter to the search-adaccount cmdlet to limit the search to the default Users container in the ad.contoso.com domain. You will need to modify the string to match your own domain name.
search-adaccount –passwordneverexpires -usersonly -searchbase "cn=users,dc=ad,dc=contoso,dc=com" | where {$_.enabled} | disable-adaccount
A safer strategy is to export the results to a text file, manually inspect and clean up the search if necessary, then parse the file using import-csv and pipe the results to a foreach loop to disable the accounts. Sounds difficult? Not at all. Note that the c:temp directory must exist before running the command.
search-adaccount –passwordneverexpires -usersonly -searchbase "cn=users,dc=ad,dc=contoso,dc=com" | where {$_.enabled} | export-csv “c:tempuserstodisable.csv”
After editing the userstodisable.csv manually, parse the file and disable the accounts:
$users = import-csv “c:tempuserstodisable.csv” foreach ($user in $users){ disable-adaccount -identity $user.distinguishedname write-host $user.name “has been disabled.” }
For more information on parsing comma-delimited text files using import-csv, see Parsing Comma-Delimited Text Files using PowerShell on Petri.