PowerShell scripts to force password change for all users after a security incident

There’s plenty to do in the aftermath of your organization suffering a security incident. Anything that can make your job quicker without compromised security is a bonus. After a confirmed or even suspected security breach, it’s often advised to to have all of your end users change their Active Directory passwords. This would of course be a nightmare to manage manually, In this post, we’ll show you how to tell if end users have recently changed their passwords and share some useful PowerShell scripts that can force your end users to complete a password change in Active Directory.

Why would you need to change every user’s password?

After a security incident, an organization might want to change every user’s password to prevent further unauthorized access and to mitigate the risk of any compromised credentials being used maliciously. This proactive step helps to ensure that even if some passwords were exposed during the incident, they can no longer be used by attackers. It also helps to restore user confidence in the security of the system and can be part of a broader strategy to enhance overall security measures.

Why use PowerShell scripts to force the mass password change?

Using PowerShell scripts can make the process of changing every user’s password much easier because it automates the task, reducing the time and effort required to manage each account individually. PowerShell scripts can efficiently interact with the organization’s directory services, such as Active Directory, to generate new, secure passwords and update them across all user accounts. This automation minimizes the risk of human error, ensures consistency in the password change process, and allows IT administrators to focus on other critical security tasks. Additionally, scripts can be scheduled to run at specific times, providing a seamless and unobtrusive way to enhance security without disrupting users’ workflows.

How to find out when a password was last changed?

You can manually check the pwdLastSet attribute on each user account to see when their password was last changed (you could also find this out by running a free scan with Specops Password Auditor and looking at password changed dates in the Password Age report). Use ADSIEdit or Active Directory Users and Computers (with advanced features enabled) to view the attribute directly:

When using PowerShell to pull the attribute, you’ll see that the attribute is actually saved in what is known as ‘filetime’ format, but you can also pull a constructed attribute called passwordLastSet which will be a DateTime PowerShell attribute (more on why that’s important in a bit).

Quick note on filetime: this is a timestamp stored as a count of the number of 100-nanosecond intervals that have elapsed since midnight on January 1, 1601 (UTC).

color meter from green to red
Are compromised passwords lurking in your AD? Audit your AD with our free tool!

Also note if you see pwdLastSet attribute is 0 (i.e. ‘never’) and passwordLastSet is blank — this means the option that the user must change their password at next logon has been enabled. This is a bit of a drawback in Active Directory as we now have no way to know when the last password change was actually performed.

Checking password change dates and times

The passwordLastSet property as a DateTime object is important because we can now manipulate the date and compare it to other dates. So if I want to run a check to say, for example, was this user’s password changed within the past 24 hours, I can add 1 day to the passwordLastSet attribute and compare it to

$user.passwordLastSet.AddDays(1) -gt $(get-date)

If we change the threshold to 30 days for this user, the result is now true (in this example, the user’s password change was about 3 weeks ago as of this blog post):

We can run this same check against all users. We’ll also exclude disabled users and any users who are already required to change their password at next logon, and check for users whose passwords never expire and/or cannot change their own password:

$verbosepreference = "continue"  
 
## Construct a date X days ago, in this case 30 days:
$compareDateTime = $(get-date).AddDays(-30)

## Alternative Option -- compare against a specific datetime by uncommenting and modifying the date in the following line:
## $compareDateTime = get-date -date "2022-03-21 12:00"
 
write-verbose "Finding users whose passwords have not changed since $compareDateTime" 
  
Get-ADUser -filter { Enabled -eq $True } –Properties pwdLastSet,passwordLastSet,passwordNeverExpires,cannotChangePassword |   
    where { $_.passwordLastSet -lt $compareDateTime -and $_.pwdLastSet -ne 0 } |   
    Select-Object name,sAmAccountName,passwordLastSet,passwordNeverExpires,cannotChangePassword
                   

How to force all users to change password

If we’d like to force all those users to change a password, we can run a script that does the same date comparison but then ticks the ‘user must change password at next logon’ option on all of them. Here we exclude any user with ‘passwordNeverExpires’ or ‘cannotChangePassword’ set to true, as you cannot require a password change on those users. We recommend a manual process to remediate these as these accounts are usually service accounts where a password change requires simultaneously updating the password in a service or application configuration.

$verbosepreference = "continue"  
 
## Construct a date X days ago, in this case 30 days:
$compareDateTime = $(get-date).AddDays(-30)

## Alternative Option -- compare against a specific datetime by uncommenting and modifying the date in the following line:
## $compareDateTime = get-date -date "2022-03-21 12:00"
 
write-verbose "Finding users whose passwords have not changed since $compareDateTime" 
  
$users = Get-ADUser -filter { Enabled -eq $True } –Properties pwdLastSet,passwordLastSet,passwordNeverExpires,cannotChangePassword |   
    where { $_.passwordLastSet -lt $compareDateTime -and $_.pwdLastSet -ne 0 -and $_.passwordNeverExpires -eq $false -and $_.cannotChangePassword -eq $false }

foreach ($user in $users) {
    $outObject = new-object -typename psobject
    $outobject | Add-member -MemberType NoteProperty -Name distinguishedName -Value $user.distinguishedname
    $outobject | Add-Member -MemberType NoteProperty -Name OldPasswordLastSet -value $user.passwordlastset
    set-aduser $user -ChangePasswordAtLogon:$true
    $outObject
} 

Scan your Active Directory today with our free tool

Specops Password Auditor is a read-only audit tool that scans your Active Directory for password-related vulnerabilities. You’ll get all the results in an easy-to-understand interactive report of user and password policy info. It’s free to download – so take the first step towards better password security. Download your free auditing tool here. 

(Last updated on February 20, 2025)

darren siegel

Written by

Darren Siegel

Darren Siegel is a cyber security expert at Specops Software. He works as a lead IT engineer, helping organizations solve complex challenges within IT security. Darren has more than 15 years’ experience within Active Directory, IT security, servers, storage, virtualization, cloud, and identity and access management.

Back to Blog

Related Articles

  • How to enforce password history in Active Directory

    The “Enforce password history” setting in Active Directory is used to determine the number of unique passwords a user must use before they can use an old password again. This is an important setting because password reuse is a common issue – the more often the same (or similar) password is used, the greater chance…

    Read More
  • Password expiration policy best practice

    Instead of arbitrarily expiring passwords every 90 or so days, why not configure the maximum password age based on the complexity level of a password?

    Read More
  • Helpdesk password reset best practices

    If your organization is currently using a self-service password reset solution, it is critical that the helpdesk staff who manage the system, and assist users, consistently follow best practices. This post will provide tips for reducing password-related calls to the helpdesk, and outline some security measures for safeguarding user accounts. Educate and direct to self-service…

    Read More