You can leverage PowerShell to get last logon information such as the last successful or failed interactive logon timestamps and the number of failed interactive logons of users to Active Directory. In this post, I explain a couple of examples for the Get-ADUser cmdlet.

Michael Pietroforte

Michael Pietroforte is the founder and editor in chief of 4sysops. He has more than 35 years of experience in IT management and system administration.

In a previous post, I explained how you can enable interactive logon logging in Active Directory. Today, I’ll show you how to use PowerShell to retrieve the information from the corresponding Active Directory attributes.

If you want to try the examples in this article on your desktop, you’ll have to install the Active Directory module for Windows PowerShell. This module is already available on every domain controller in an Active Directory domain with a functional level of Windows Server 2008 R2 or higher.

Note that I will only discuss the last interactive logon attributes in this article. However, you can also use the examples in this post for the lastLogon and lastLogontimeStamp attributes, which are useful for listing inactive accounts if you replace the attributes in the commands accordingly.

As discussed in my previous article, you can use the interactive logon attributes for gathering real-time information about the last successful (msDS-LastSuccessfulInteractiveLogonTime) and unsuccessful (msDS-LastFailedInteractiveLogonTime) user logon times. In addition, you can retrieve the number of failed logons (msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon) of a user account since the last successful logon, as well as the failed logons since the feature was enabled (msDS-FailedInteractiveLogonCount).

Note: After I finished this post, I noticed that the msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon attribute does not store the correct value. Even though the information is correctly displayed on the logon screen, msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon always has the same value as msDS-FailedInteractiveLogonCount. This appears to be a bug in Windows Server 2012 R2. It is not a PowerShell issue because I also see the wrong values in ADUC. Please let me know if you get the same results in your tests.

The cmdlet we need to gather the information is Get-ADUser, which enables you to query information about Active Directory user objects. The easiest case would be if you want to know the number of failed logons since the last successful logon for a particular user. For example:

The number of failed logons since the last successful logon for a particular user

You can use the Filter parameter to search for user objects that have a certain attribute value. In the example, we restrict the output to the Administrator account. The Properties parameter is required because the interactive logon attributes are not included in the default set of properties (attributes) that the Get-ADUser cmdlet retrieves. By using the asterisk, we display all of the attributes that are set on the user object. We then pipe the output to the Select-Object cmdlet, which restricts the output to the name of the user account and the number of failed logons at the last successful logon.

If you want to find out what account logout threshold you should configure in your network, you could create a list that is sorted according to the number of failed logons at the last successful logon:

The number of failed logons since the last successful logon

If you run the above command every day for a week or so, you will get a feeling for how often users mistype their passwords.

Or perhaps you just want to know how many of your users would fall prey to your account logout threshold. The command below counts the number of users who mistyped their password more than three times since the last successful logon:

The number of users who mistyped their password more than three times since the last successful logon.

Things get a bit trickier if you want to know the time of the last failed logon. The problem is that the attribute stores this information in the Windows file time format, a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601. If you don’t happen to be Rain Man, you have to let the computer convert the value into a human-readable format. For this, we use the .NET method DateTime.FromFileTime, which converts the Windows file time to an equivalent local time. This is how you could display the last failed interactive logon time for the Administrator account:

The last failed interactive logon time for the Administrator account

The @{} syntax creates a hash table, which is just a collection of key-value pairs. In our case, we have two pairs: the Name key, which has the value “Last failed logon time,” and the Expression key, for which we calculate the value with the above-mentioned .NET method. “$_” stands for the user object that we pipe to the Select-Object cmdlet. We use this hash table as a calculated property that allows us to select the property and convert it into a human-readable format.

If you suspect that someone is trying to hack accounts in your network by guessing passwords, you might want to create a list of all user accounts with all four interactive logon attributes. If you notice that some accounts have unusually high numbers of failed logons since you activated the feature, but those accounts were never locked, someone might be aware of your password account threshold and patiently tries just a few passwords every day. Of course, another explanation would be that your users really need new keyboards. 😉

List of all users with all their interactive logon attributes

If you see “31/12/1600” as a date, it doesn’t mean that one of your users possesses a time machine. This user just never logged in interactively.

Another piece of interesting information could be the time difference between the last successful logon and the last unsuccessful one.

The time difference between the last successful logon and the last unsuccessful one

The first line calculates the time difference using a .NET function and then formats the value in human-readable format (days, hours, minutes, seconds). In the last line, we again use a hash table to display the result. We need the GetEnumerator() method so we can sort our hash table.

Please let me know if you could confirm the bug regarding the failed logon counts I mentioned above.

Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!

0
Share
20 Comments
  1. Marc Laflamme 5 years ago

    All I got for results were { }. Maybe it's because I'm still running 2000 Native?

    0

  2. Michael Pietroforte 5 years ago

    Marc, are you serious? Domain functional level Windows 2000 native? You are telling me that you didn't upgrade your Active Directory in 15 years? You need functional level Windows Server 2008 R2 or higher and you have to enable the feature first with Group Policy.

    2+

  3. Marc Laflamme 5 years ago

    Michael, boy do I feel sheepish! In my defence, I've only been here for 7 years (and a sysadmin for 3)... It's actually on my project plan this year! Still trying to decide on whether or not to virtualize the DC's. If going physical and we can get some new hardware I'd like to do 2012 but if not then 2008 R2.

    0

  4. Michael Pietroforte 5 years ago

    Marc, don't move to 2008 R2. This is yesterday's technology. If you are going to virtualize your domain controllers you will want to have latest OS that is adapted to this environment.

    0

  5. Marc Laflamme 5 years ago

    Michael,

    Is there anywhere I can ask you a few questions other than these comments?

    0

  6. Michael Pietroforte 5 years ago

    Marc, you can ask questions in the forum.

    0

  7. Adam Hamilton 5 years ago

    It would be better to retrieve only the 2 extra properties you need rather than all of them. In a large AD environment performance could be awful.

    0

  8. Michael Pietroforte 5 years ago

    Adam, that's a good point!

    0

  9. matt 5 years ago

    I got all dates as 12/31/1600 and i'm on DFL 08 R2...strange stuff.

    0

  10. Nick 4 years ago

    I too got all dates as 12/31/1600 and i'm on DFL 2012.

    0

  11. Peter 4 years ago

    Same here - all showing 01/01/1601, DFL 2008R2

     

     

    1+

  12. Marcos Pinto 4 years ago

    This is what worked for me:

    Get-ADUser -Filter * -Properties * | Select-Object Name, @{Name="Last Successful Logon";Expression={[datetime]::FromFileTime($_.'lastLogonTimeStamp')}} | Sort-Object "Last Successful Logon"

    10+

  13. lenin 3 years ago

    I also want to get who/which account made this logon. For example:

    [/crayon]

    0

  14. roarke christian 3 years ago

    I need to have 2  reports (csv or txt):

    one that includes "Active users" and their "last login date"

    another that included "de-active users" and their "last login date".

     

    I know I can use "get-aduser -filter 'enabled -eq $false' to generate a listing in powershell, but that only shows users without last login date, and is not exported to (csv or txt).

    0

  15. Anbu 2 years ago

    thanks

    0

  16. Mike Coleman 8 months ago

    Get-ADUser -Filter * -Properties * | Select-Object Name, @{Name="Last Successful Logon";Expression={[datetime]::FromFileTime($_.'lastLogonTimeStamp')}} | Sort-Object "Last Successful Logon"  | Write-output c:\temp\lastloggedon.csv

    That is what worked for me to get all the last logons so I could see accounts that have not logged in for over a year so I could disable them.

    0

  17. Tyson Cooper 5 months ago

    Hello Michael, This might be a dumb question, but since I can't seem to find the answer elsewhere I thought I would ask you directly. By means of background, I am analysing an estate with a massive amount of service accounts... and over time a lot of these have been used by IT staff to login interactively to the servers running the services the service accounts are being used for. Lazy practice and definitely not good security policy for sure...  but we are cleaning this up. We are now denying interactive logons via group policy but only after thorough investigation of each active service account. To summarise, when I pull the attribute msDS-LastSuccessfulInteractiveLogonTime, I am still seeing a very large number of my service accounts with a value being set every few minutes....  and this value is matching the 'LastLogon' attribute. It's as if 'Lastlogon' is being set as 'msDS-LastSuccessfulInteractiveLogonTime' as well. I've confirmed this isn't just in Powershell...  it's reflected in the ADUC Attribute Editor tab too for these accounts. And yes, I have confirmed there is literally no way all of these are in fact being used for interactive logons... in fact most are in the deny policy.

    So I guess the question from all of the above is...  what else OTHER than an actual interactive logon to the console or via RDP would result in the 'msDS-LastSuccessfulInteractiveLogonTime' attribute being set?

    0

    • Author
      Michael Pietroforte 5 months ago

      As far as I know, the attribute exactly stores the info that its name suggests. Maybe there is something wrong with your deny policy?

      0

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2019

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account