- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
There have probably been cases when you needed to track down a potential security breach or perhaps you had managers come to you because they suspected employees weren't working quite as hard as they should be. In any case, it was important that you figure out the amount of time the users logged onto a computer interactively in your Active Directory domain.
Being the excellent administrator you are, you might have gotten on Google and tried to figure this out; if so, you'd soon find that it's possible to get Windows to write events to the Security event log after a user logs on and logs off. "Great," you think. "All I need to do now is to grab those two events and figure out the difference to get the total session time." After digging a little deeper though, you'd soon realize that it's not quite that easy. It's possible for a session to be more than a simple user logon and logoff. What if the computer crashes? What if the user decides just to pull the plug? What if they're using Remote Desktop Protocol (RDP) to log into a server? These different scenarios may come into play, and you may need to account for them.
Tracking the past and present user session times accurately across multiple computers requires a few steps to make this happen.
- You must "turn on" the ability for the computers to begin logging this activity. You can do this through Active Directory auditing. You must enable and the appropriate audit policies and target them to the computers on which you'd like to track users.
- You must figure out which events correlate to the starting and stopping points for a user session. A user logon would be a good starting point, for example, and a computer shutdown would be a good stopping point, but there are many other combinations as well.
- You must figure out how to correlate a single session stop and an end event with a common identifier. You'll see that this is possible with a logon ID and a little bit of ingenuity to match up the others.
- You must have a method to query the event logs from all targeted computers to find all relevant events.
- You must be able to correlate a start session event and a stop session event, and finally take the difference between those to come up with the total time a user interactively logged in to a computer.
Enabling Active Directory auditing policies ^
The first task is to ensure your computers are generating the necessary events in their event logs. To do this, you'll need to enable three advanced AD audit policies: Audit Logoff, Audit Logon, and Audit Other Logon/Logoff Events. Combined, these three policies get you all of the typical logon and logoff events. In addition, the policies also get the workstation lock/unlock events, and even RDP connect/disconnects. This ensures we get all of the session start/stop events.
As you can see in the screenshot, I chose to create a Group Policy Object (GPO) called User Session History and set all to Success.
Defining session start and stop events ^
Once each computer picks up this GPO, it will begin generating a few different event IDs you should be concerned about. It's important to match up each of these events to a start or stop event. After defining these, you are then able to match up each one in the event logs and calculate the difference in time to come to an accurate total session time.
|Event||Event ID||Event Log||Session Start/Stop|
|RDP Session Reconnect||4778||Security||Start|
|RDP Session Disconnect||4779||Security||Stop|
All of these events are self-explanatory except for one that I should point out. You'll notice that I have a startup event with event ID 6005 labeled as a stop session event. Why? Because we'll use this event ID when the computer suddenly gets shut off without warning. Think of instances when the power goes out, or someone simply pulls the cord. There's no way to come up with a "logoff" time. The best we can do is figure out the next time the user came on. It's not an accurate representation, but it's the closest we'll be able to get.
Matching up start and stop session events ^
Once we've got all the IDs put together, we'll then need to match the session start event with the very next session end event. This might seem trivial, but in actuality, this is the hardest part of this process.
For many of the session start and stop events, Windows generates a unique Logon ID field. You can use this field to correlate a start and a stop session time. It is unique for each user logon session. If we can find a session start time and then look through the event log for the next session stop time with the same Logon ID, we've found that user's total session time.
You can see in the first screenshot above that the Administrator account on the LAB domain logged onto a computer called WIN81x86-1 on 10/3/15 at 11:02:05 AM. This generated event ID 4624 and is using the Logon ID of 0xD72BAA. Then, in the next screenshot, the computer generated an event ID 4647 at 11:03:28 AM when the user logged off and has a reference to that same Logon ID.
By matching up these two events and taking the difference in time, I can now see that the Administrator user account logged onto the computer for 1 minute and 23 seconds.
This was just a quick demonstration of actual logon/logoff scenarios. You'll find that when you review a computer in the "real world," you can't always depend on logon/logoff events if you'd like to find user session durations. Multiple scenarios may come into play, such as when a user locks her computer and comes back to unlock it. Perhaps she may lock her computer, and the power gets cut. There will be no unlock event; only a startup event. You need to watch out for these gotchas to be able to calculate user session history accurately.
A user session could consist of combinations of any of the following events.
|Start Event||Stop Event|
|User Logon||User Logoff|
|User Logon||Computer Startup|
|User Logon||RDP Session Disconnect|
|RDP Session Reconnect||RDP Session Disconnect|
|RDP Session Reconnect||User Logoff|
|RDP Session Reconnect||Locked|
|RDP Session Reconnect||Computer Startup|
|Unlocked||RDP Session Disconnect|
Now you see what you might think is an easy task quickly turns into something much more difficult to track accurately!
Using PowerShell to automate user login detection ^
Since the task of detecting how long a user logged on can be quite a task, I've created a PowerShell script called Get-UserLogonSessionHistory.ps1 available on Github. This script allows you to point it at a local or remote computer, query the event log with the appropriate filter, and return each user session.
Subscribe to 4sysops newsletter!
ComputerName : FUSIONVM Username : Adam StartTime : 12/30/2016 9:01:52 AM StartAction : Logon StopTime : 1/22/2017 9:53:45 AM StopAction : Logoff Session Active (Days) : 23.04 Session Active (Min) : 33171.89 ComputerName : DESKTOP-AVEQ7UN Username : Adam StartTime : 12/30/2016 8:54:14 AM StartAction : Logon StopTime : 12/30/2016 9:01:19 AM StopAction : Logoff Session Active (Days) : 0 Session Active (Min) : 7.08 ComputerName : DESKTOP-AVEQ7UN Username : Adam StartTime : 12/30/2016 8:47:37 AM StartAction : Logon StopTime : 12/30/2016 8:53:07 AM StopAction : Logoff Session Active (Days) : 0 Session Active (Min) : 5.49 ComputerName : DESKTOP-AVEQ7UN Username : Adam StartTime : 12/30/2016 8:43:50 AM StartAction : Logon StopTime : 12/30/2016 8:47:04 AM StopAction : Logoff Session Active (Days) : 0 Session Active (Min) : 3.23 ComputerName : DESKTOP-AVEQ7UN Username : defaultuser0 StartTime : 12/30/2016 8:42:39 AM StartAction : Logon StopTime : 12/30/2016 8:43:49 AM StopAction : Logoff Session Active (Days) : 0 Session Active (Min) : 1.18