Active Directory provides several methods for determining when a user has logged on to the domain. The time of a user’s last successful authentication in Active Directory can be retrieved from the lastLogon attribute (which is updated only on the domain controller that handled the authentication) or from the lastLogonTimestamp attribute (replicated across all DCs, but only if it is 14 days or more older). The values of these user attributes can be viewed using either the AD attribute editor or the Get-ADUser PowerShell cmdlet. However, this will only give you the last time the user logged in. Sometimes, you need to view the history of a user’s logon activity in a domain over an extended period of time.
In this article, we’ll cover how to configure a Group Policy to audit user authentication events in a domain and use PowerShell to collect information about successful user logons from the domain controller’s security logs. With a simple PowerShell script, you can quickly retrieve a complete history of user activity in a domain, including logon times and the computers from which they logged on.
[contents h2]
Configure User Logon Audit Policy in Active Directory
To collect successful and failed user logon events in the security logs of the AD domain controller, you must configure an audit policy.
- Open the domain GPO management console (
GPMC.msc
) - Create a new GPO and link it to the domain root (it is not recommended to edit the Default Domain Policy)
- Open the new GPO settings and go to Computer Configuration -> Policies -> Windows Settings -> Security Settings –> Advanced Audit Policy Configuration -> Audit Policies -> Logon/Logoff
- Enable two audit policies (Audit Logon and Audit Other Logon/Logoff Events). Select Success and (optionally) Failure options in the audit policy settings to register both successful and failed logons in the Security log on the DCs and computers.
- Next, enable auditing for Kerberos authentication events. Go to Audit Policies -> Account Logon –> Audit Kerberos Authentication Service -> enable audit of Success events.
- Save the changes to the GPO
- Wait for the new GPO to be replicated between DCs
- Domain controllers apply GPO settings every 5 minutes. Or manually update the Group Policy settings by using the command:
gpupdate /force
Now, when a user logs in to any computer in an Active Directory domain, an Event ID 4624 (An account was successfully logged on) will appear in the Security log of the domain controller that authenticates the user (LogonServer). The event description includes the authenticated user’s Account Name, Workstation Name, or IP address (Source Network Address) of the computer from which the logon was performed.
The Logon Type field of the event contains the user’s logon type (code). We may be interested in the following login codes:
- Logon Type 2 – interactive (local) login to computer: An account was successfully logged on
- Logon Type 3 – Network logon (occurs when a user authenticates on a DC, connects to a shared network folder, printer, or IIS service).
- Logon Type 10 – Remote Interactive logon – remote login via terminal services (RDP), shadow connection, or Remote Assistance. This event is used to monitor and analyze the activity of Remote Desktop Services users.
- Logon Type 7 – User session unlock event (after manual or automatic computer screen lock after inactivity).
You can also track a user’s domain login by monitoring the Kerberos ticket issuance event during user authentication.
Event ID 4768:
A Kerberos authentication ticket (TGT) was requested.
Event 4768 contains the name (or IP address) of the computer and the user account (Account Name or User ID) that received a Kerberos ticket, indicating successful authentication.
How to Get AD User Login History with PowerShell
You can use the Get-Eventlog PowerShell cmdlet to get all events from the domain controller’s event logs, filter them by the EventID you want, and display information about the time when a user authenticated in the domain and a computer used to log on. Since there may be multiple domain controllers in your domain and you may want to get a user logon history from each of them, use the Get-ADDomainController cmdlet (from the AD module for Windows PowerShell). The cmdlet allows you to get the list of all DCs in your domain.
Let’s look at how to use PowerShell to extract user login events from domain controller security logs. Because a domain can have multiple domain controllers, each with its own Security log, you will need to search for events on each DC
The original version of the script used the Get-Eventlog cmdlet to retrieve events with a specific EventID from the domain controllers’ security logs. A sample PowerShell script that lists the logon events for a specified user for the last 2 days from all domain controllers:
# A username for which you want to view the logon history
$checkuser='*jbrown*'
# Get user login history for the last 2 days (you can change this value)
$startDate = (get-date).AddDays(-2)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
$logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $startDate -ComputerName $dc.HostName
foreach ($event in $logonevents){
if (($event.ReplacementStrings[5] -notlike '*$') -and ($event.ReplacementStrings[5] -like $checkuser)) {
# Remote (Logon Type 10)
if ($event.ReplacementStrings[8] -eq 10){
write-host "Type 10: Remote Logon`tDate: "$event.TimeGenerated "`tStatus: Success`tUser: "$event.ReplacementStrings[5] "`tWorkstation: "$event.ReplacementStrings[11] "`tIP Address: "$event.ReplacementStrings[18] "`tDC Name: " $dc.Name
}
# Network(Logon Type 3)
if ($event.ReplacementStrings[8] -eq 3){
write-host "Type 3: Network Logon`tDate: "$event.TimeGenerated "`tStatus: Success`tUser: "$event.ReplacementStrings[5] "`tWorkstation: "$event.ReplacementStrings[11] "`tIP Address: "$event.ReplacementStrings[18] "`tDC Name: " $dc.Name
}
}
}
}
The output is a table that includes the user’s logon history, the computers from which the user authenticated, and the domain controllers that processed the logon.
The main drawback of the Get-EventLog cmdlet is its slow event search performance. Instead, it’s better to use the faster Get-WinEvent cmdlet to find events. Here’s an example of a similar PowerShell script to get logon events from all domain controllers, which will search much faster
$TargetUsername = 'jbrown' $StartTime = (Get-Date).AddHours(-48) $LogonTypeDescriptions = @{ '2' = 'Interactive' '3' = 'Network' '7' = 'Unlock' '10' = 'RemoteInteractive' '11' = 'CachedInteractive' } $DomainControllers = Get-ADDomainController -Filter * $LogonEvents = @() foreach ($DC in $DomainControllers) { $FilterHashtable = @{ LogName = 'Security' ID = 4624 StartTime = $StartTime } $Events = Get-WinEvent -ComputerName $DC.HostName -FilterHashtable $FilterHashtable -ErrorAction SilentlyContinue foreach ($Event in $Events) { $EventData = [xml]$Event.ToXml() $EventUser = $EventData.Event.EventData.Data[5].'#text' $LogonTypeCode = $EventData.Event.EventData.Data[8].'#text' if ($EventUser -eq $TargetUsername) { $LogonEvent = [PSCustomObject]@{ TimeCreated = $Event.TimeCreated ComputerName = $EventData.Event.EventData.Data[18].'#text' IPAddress = $EventData.Event.EventData.Data[18].'#text' Username = $EventUser LogonType = $LogonTypeDescriptions[$LogonTypeCode] DCName = $DC.HostName } $LogonEvents += $LogonEvent } } }
Use the Export-Csv cmdlet to export a user’s logon history to a CSV file:
$FileName = "C:\PS\LogonEvents" + $startDate.ToString('yy_MM_dd') + ".csv"
$LogonEvents| Export-Csv $FileName -Append -NoTypeInformation -encoding UTF8
Get Domain User Logon History Based on Kerberos Events
You can also get a user authentication history in the domain based on the event of a Kerberos ticket being issued (TGT Request, EventID 4768). In this case, fewer events will appear in the output because network logins and DC folder access events (such as when retrieving GPO files or running login scripts) are excluded. The following PowerShell script displays information about all user logons for the past 24 hours:
$alluserhistory = @()
$startDate = (get-date).AddDays(-1)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
$logonevents = Get-Eventlog -LogName Security -InstanceID 4768 -after $startDate -ComputerName $dc.HostName
foreach ($event in $logonevents){
if ($event.ReplacementStrings[0] -notlike '*$') {
$userhistory = New-Object PSObject -Property @{
UserName = $event.ReplacementStrings[0]
IPAddress = $event.ReplacementStrings[9]
Date = $event.TimeGenerated
DC = $dc.Name
}
$alluserhistory += $userhistory
}
}
}
$alluserhistory
Note that in this case, you won’t see any logon events for users authenticated by clients or applications that use NTLM instead of Kerberos
4 comments
Second script does not display anything
For first script, how to save out to a csv file.
| export-csv
When a user logs on to a Windows computer, 4624 event logs occur. However, in many cases, including connecting over a network, remote desktop connection, and unlocking the locked computer, event 4624 is still logged. The following table can be viewed as the types of logins (Logon Type) :
Logotype Logo Title Description
0 System It is only used for the “System” account.
2 Interactive Actual login event.
3 Network Network login. For example, accessing a share.
4 Batch Batch logon type is used by batch servers, where processes may be executing on behalf of a user without their direct intervention.
5 Service A record of a service started by the Service Control Manager.
7 Unlock Record of unlocking the locked computer.
8 NetworkCleartext A user is logged on over the network, but the password was sent explicitly, not as a hash.
9 NewCredentials The token generated at login was reused but specified new login information (username and password).
10 RemoteInteractive Connection to remote desktop established.
11 CachedInteractive The domain server (DC) was not consulted to verify the password at login, the local registration information (cache) was used.
12 CachedRemoteInteractive Same as RemoteInteractive, tried(?) for internal monitoring
13 CachedUnlock I guess it’s the case of using local cache information without consulting DC when unlocking.
If we are looking for logins to a non-domain computer we should look at 2 or 7. For a domain member computer, it can be 2, 11, and 13.
With a Get-WinEvent query like this, it will most likely not be possible to see all the information in the event body:
PS> Get-WinEvent -Filterhashtable @{LogName=”Security”;Id=4624}
Instead, it is possible to take into account the login type and produce a better output with the EventProperty object. Here are the EventProperty members for event 4624:
0 : Subject User SID
1 : Subject Username
2 : Subject Domain Name
3 : Subject Logon Id
4 : Target User SID
5 : Target Username
6 : Target Domain Name
7 : Target Logon Id
8 : Logon Type
9 : Logon Process Name
10: Authentication Package Name
11: Workstation Name
12: Logon GUID
13: Transmitted Services
14: LmPackageName
15: Keylength
16: ProcessId
17: ProcessName
18: IP Address
19: IP Port
20: Impersonation Level
21: Restricted Admin Mode
22: Target Outbound Username
23: Target Outbound Domain Name
24: Virtual Account
25: Target Linked Logon Id
26: Elevated Token
The following details are given for member Status 4 in the EventProperty object of the 4771 Pre-Authentication failed error :
status Kerberos RFC definition Explanation
0x1 Client’s entry in database has expired
0x2 Server’s entry in database has expired
0x3 Requested protocol version # not supported
0x4 Client’s key encrypted in old master key
0x5 Server’s key encrypted in old master key
0x6 Client not found in Kerberos database Bad user name, or new computer/user account has not replicated to DC yet
0x7 Server not found in Kerberos database New computer account has not replicated yet or computer is pre-w2k
0x8 Multiple principal entries in database
0x9 The client or server has a null key administrator should reset the password on the account
0xA Ticket not eligible for postdating
0xB Requested start time is later than end time
0xC KDC policy rejects request Workstation restrictions
0xD KDC cannot accommodate requested option
0xE KDC has no support for encryption type
0xF KDC has no support for checksum type
0x10 KDC has no support for padata type
0x11 KDC has no support for transited type
0x12 Clients credentials have been revoked The account is inactive, expired, locked, or out of sign-in hours.
0x13 Credentials for server have been revoked
0x14 TGT has been revoked
0x15 Client not yet valid – try again later
0x16 Server not yet valid – try again later
0x17 Password has expired The password has expired
0x18 Pre-authentication information was invalid Often wrong password
0x19 Additional pre-authentication required*
0x1F Integrity check on decrypted field failed
0x20 ticket expired Frequently logged by computer accounts
0x21 Ticket not yet valid
0x21 Ticket not yet valid
0x22 Request is a replay
0x23 The ticket isn’t for us
0x24 Ticket and authenticator don’t match
0x25 Clock skew too great Workstation’s clock too far out of sync with the DC’s
0x26 Incorrect net address IP address change?
0x27 Protocol version mismatch
0x28 Invalid msg type
0x29 Message stream modified
0x2A Message out of order
0x2C Specified version of key is not available
0x2D Service key not available
0x2E Mutual authentication failed may be a memory allocation failure
0x2F Incorrect message direction
0x30 Alternative authentication method required*
0x31 Incorrect sequence number in message
0x32 Inappropriate type of checksum in message
0x3C Generic error (description in e-text)
0x3D Field is too long for this implementation
Using these, a command like this is possible for a more shaped output:
PS> Get-WinEvent -FilterHashtable @{LogName=”Security”;Id=4624} |
Where-Object {$_.properties[8].Value -eq 2} |
Select-Object TimeCreated, Id, @{Name=”Username”;Expression={$_.properties[5].Value}}, @{Name=”LogonProcName”;Expression={$_.properties[9].Value }}, @{Name=”AuthPkgName”;Expression={$_.properties[10].Value}}, @{Name=”IPAddress”;Expression={$_.properties[18].Value}}
Logout event 4634, login failure (wrong password/username) can be queried with events 4625. There are 5 fields in the EventProperties object for logout. In 4625, there are fields in number and quality similar to 4624.