In Active Directory (AD), the PasswordLastSet and pwdLastSet attributes refer to the same property of an AD object – the time and date when the password for that object was last changed. This attribute is used to enforce password policies and track when a password was last changed.

This quick post helps you understand these two values and how to call them using PowerShell.

Prerequisites

Get your PowerShell ready and ensure you have the proper permission, such as Domain Admin.

Also, it would be best if you had Active Directory PowerShell Module.

What is PwdLastSet vs PasswordLastSet

The PwdLastSet attribute is an Active Directory attribute that stores information about the last time a password was changed for an object. This value type is a LargeInteger representing dates as the number of 100-nanosecond intervals since January 1, 1601, 12:00 AM. The time is always stored in Greenwich Mean Time (GMT). The PasswordLastSet property converts this LargeInteger into a date-time value in the current time zone.

When working with AD Users object, reading the PasswordLastSet is much easier than reading the PwdLastSet. Check the example below for more details.

Get-ADuser ValidUser -Properties PasswordLastSet,PwdLastSet | Select-Object Name,PasswordLastSet,Pwdlastset

Name         PasswordLastSet               Pwdlastset
----         ---------------               ----------
ValidUser    20-Jan-23 11:26:54 AM      132739180149651303

The PasswordLastSet is derived from the AD attribute PwdLastSet.

If a password is not set, the PwdLastSet value is 0, and PasswordLastSet will be absent. In cases were the “User must change password at next logon” option is selected in ADUC, the PwdLastSet value will be set to 0, resulting in the absence of PasswordLastSet.

Get-ADuser Test -Properties passwordlastset,pwdlastset | Select-Object Name,PasswordLastSet,Pwdlastset

Name PasswordLastSet Pwdlastset
---- --------------- ----------
Test                          0

If a user has a recent value for LastLogon but is missing PasswordLastSet, it indicates that the user must change their password at their next logon, with PwdLastSet being set to 0.

the PasswordLastSet and PwdLastSet attributes are replicated across all domain controllers in an Active Directory (AD) environment. The replication of this attribute ensures that all domain controllers have the same value for a user’s password last set time. This allows for consistent enforcement of password policies and helps to ensure the security of the AD environment.

Getscreen.me is a cloud-based software providing a remote access via a browser. Connection is performed via a link without installing additional programs. The service is suitable for administration, technical support, as well as for remote connection to an office computer from home. Windows, macOS, Linux and Android versions are available.

get screen

UserAccountControl And Password Never Expires Using PowerShell

Another possible case for PwdLastSet to be 0 can be:

  • The account was created, but the password was never set.
  • The administrator created an AD user account, and the password was set while creating the user, but the User Must Change Password at Next Logon was checked.
  • The administrator has checked the User Must Change Password at Next Logon option for the user in the AD user property.

Multiple ways to check if the Password Never Expires option is selected. For instance, you can check the user property using ADUC, or using PowerShell AD User property PasswordNeverExpires.

But let’s go a bit deeper and discover the roots of this value by digging into the UserAccountControl value.

The UserAccountControl represents some basic properties for the AD account status like, account enabled, disabled, Password Never Expires…and more. Reading the value from ADUC for an AD User shows a decimal number such as 512 which means that the account is normal and active.

The Password Never Expires value is 65536. Adding these two values together, 65536+512=66048

UserAccountControl property
UserAccountControl property

But where did these values come from? The UserAccountControl is 4 Bytes which contains 32 bits (Binary). These are bits flags (1 or 0). The Password Never Expires bit is the 15th bit. So some conversion may be required to convert the value from decimal to binary.

An easy and comprehensive explination about these bits can be found in SelfADSI.org , Attributes for AD Users : userAccountControl

Luckily PowerShell has an easy way to find these accounts without having to go through the hassle of reading and converting the value from decimal to binary. Here is an example code

PS> Get-ADUser Test -Properties PwdLastSet,PasswordNeverExpires | Select-Object Name,PwdLastSet,PasswordNeverExpires


Name PwdLastSet PasswordNeverExpires
---- ---------- --------------------
Test          0                 True

If you want the complex way and want to convert the value to binary and read it. No worry, here is the code.

$UAC=Get-ADUser Test -Properties UserAccountControl
$binary = [Convert]::ToString($UAC.UserAccountControl, 2).PadLeft(32, '0')

if ($binary.Chars(15) -eq [System.Convert]::ToString('1',2)){Write-Host "$($UAC.Name) Password is set to never expires"}

Test Password is set to never expires

You might need this conversion method to find a certain bit property of a user.

How To Change PwdLastSet Attribute

To change the value of the PwdLastSet attribute, you can use various tools such as the Active Directory Users and Computers console, the Set-ADUser cmdlet in PowerShell, or an LDAP editor such as LDP.

The possible values that PwdLastSet can hold are:

  • 0: Indicates that the password has never been set.
  • -1: Indicates that the password does not expire. This doesn’t mean that the password will never expire. But, once the user login after the PwdLastSet is set to -1, the date and time value of the PwdLastSet is set to the corresponding current date/time.
  • any other value: Represents the date and time when the password was last changed as a large integer representing the number of 100-nanosecond intervals since January 1, 1601.

You can only set the value of the PwdLastSet to 0 or -1. No other value is accepted.

How to Reset PwdLastSet using PowerShell

You can reset this value using PowerShell using the following steps:

  • Start PowerShell and import the Active Directory PowerShell module.
  • Type the following code.
Set-ADUser -Identity test -Replace @{'Pwdlastset'='0'}

Or you can use the -1 instead of 0

Set-ADUser -Identity test -Replace @{'Pwdlastset'='-1'}

How to read the PwdLastSet value

The PwdLastSet value is a long number, something like this 132739180149651303. To read this value first, we need to convert it to a date and time we can understand.

Using PowerShell, we can use the FromFileFormat method from the DateTime class.

To call a class in PowerShell, use the class name between brackets [ ], so its [DateTime] and to call the method in the class, use a double-colon :: and type the FromFileFormat method.

The method requires input to take action, so pass the PwdLastSet as the input.

The full PowerShell cmdlet looks like

[Datetime]::FromFileFormat($_.PwdLastSet)

Take a look at What is PowerShell and Why to use it post to learn more about PowerShell and PowerShell classes.

Read PwdLastSet with Get-ADUser

To read the PwdLastSet attribute of an Active Directory User, we can use the Get-ADUser cmdlet in PowerShell. For example, to retrieve the PwdLastSet value for a user with the SamAccountName “Test“, we can run the following line.

PS> $DateTimeValue=(Get-ADUser Test -Properties PwdLastSet).PwdLastset
[DateTime]::FromFileTime($DateTimeValue)

03-Feb-23 3:35:00 PM

To display user information along with PwdLastSet, use the following line

The DateTime conversion happens in an expression within the Select-Object


PS> Get-ADUser Test -Properties PwdLastSet | Select-Object Name,UserPrincipalName,@{N="PasswordDate";e={[DateTime]::FromFileTime($_.Pwdlastset)}}

Name UserPrincipalName PasswordDate        
---- ----------------- ------------        
Test Test@Domain.com 03-Feb-23 3:35:00 PM

Review Accounts where the PwdLastSet is zero (User Must Change Password Next Login)

Using the PowerShell line below, you can get a list of all Active Directory users that have the PwdLastSet equal to zero, which means that the user must change the password next login.

PS> Get-ADUser -Properties PwdLastSet -Filter 'PwdLastSet -eq 0'


DistinguishedName : CN=User1,DC=Domain,DC=com
Enabled           : True
GivenName         : User1
Name              : User1
ObjectClass       : user
pwdlastset        : 0
SamAccountName    : User1
UserPrincipalName : User1@domain.com

Get All AD Users with Password Ages Older Than X Number of Days

You might need to run a query in your Active Directory to get a list of users with passwords older than a number of days. This can be a good start to sending users a notification about their password expiry so they change it before it expires.

$PasswordOlderThan=(Get-date).AddMonths(-1)
Get-ADUser -Properties PasswordLastSet -Filter 'PasswordLastSet -lt $PasswordOlderThan' | Select-Object Name,PasswordLastSet

The output is a list of users with passwords older than one month.

Name       PasswordLastSet      
----       ---------------      
test-it    25-Sep-20 1:41:45 PM 
test2      07-Jan-16 12:50:51 PM
Test3      03-May-21 1:49:54 PM 

Using msDS-UserPasswordExpiryTimeComputed

Another way to handle password expiry in Active Directory is using the msDS-UserPasswordExpiryTimeComputed. This attribute is a computed time for when the AD object password will expire. This attribute is great as it saves us some small calculations to know when the user’s password will expire. This can also be very helpful when using multiple password policies.

So if User1 password is set on the 1st of Jan and the password expiry policy is after 15 days. the msDS-UserPasswordExpiryTimeComputed will be the 15th of Jan.

The msDS-UserPasswordExpiryTimeComputed value calculation is the same as PwdLastSet, a none readable date format. We can use the same method for the PwdLastSet to convert it to a readable format.

Please note that the msDS-UserPasswordExpiryTimeComputed is blank if Password Never Expire is checked.

One other thing is that msDS-UserPasswordExpiryTimeComputed takes in to account Fine Grained Password Policies. So if a AD user is assigned a Fine Grained Password Policies and the policy dont require a password age, then the msDS-UserPasswordExpiryTimeComputed will be never, even though the Password Never expires is not checked

A great comment and addition to this post from Adam D

This can be problematic in some environments as not all applications honor fine-grained password policies, such as Citrix Storefront

PS > Get-ADUser -Properties PasswordLastSet,msDS-UserPasswordExpiryTimeComputed -Filter * | Select-Object Name,PasswordLastSet,@{N="msDS-UserPasswordExpiryTimeComputed";E={[datetime]::FromFileTime($_.'msDS-UserPasswordExpiryTimeComputed')}}

Name     PasswordLastSet       msDS-UserPasswordExpiryTimeComputed
----     ---------------       -----------------------------------
test2    04-Feb-23 10:54:50 AM                                    
                                   

test     03-Feb-23 4:15:02 PM  04-May-23 4:15:02 PM

Thats for today. Looking to read more? We got some for you, and also join me to be inform once a new post is released.

1.4/5 - (216 votes)