Have you ever received a ticket where a user failed to log into a system? You call them up and find out they are now locked out of their account? You offer to reset their password but receive the story on how they typed in their password correctly and the system is messing up.
Often, we receive these requests but instead of troubleshooting what the customer says, troubleshoot what the server says. There is a useful log you can view, labeled as "Windows Security Log Event ID 4625". Inside the log, you will find valuable information such as what the user typed in as their username if the user used a domain value or not. What we find useful about this log is being able to see if the user forgot to use a domain when accessing a remote system.
Logon Type
You can first check how a user attempted to log into a system using the data we pulled directly from Microsoft's documentation.
| | |
2 | Interactive | A user logged on to this computer. |
3 | Network | A user or computer logged on to this computer from the network. |
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 service was started by the Service Control Manager. |
7 | Unlock | This workstation was unlocked |
8 | NetworkCleartext | A user logged on to this computer from the network. The user's password was passed to the authentication package in its unhashed form. The build-in authentication packages all hash credentials before sending them across the network. The credentials do not traverse the network in plaintext (also called cleartext) |
9 | NewCredentials | A caller cloned its current token and specified new credentials for outbound connections. The new logon session has the same local identity but uses different credentials for other network connections. |
10 | RemoteInteractive | A user logged on to this computer remotely using Terminal Services or Remote Desktop. |
11 | CachedInteractive | A user logged on to this computer with network credentials that were stored locally on the computer. The domain controller was not contacted to verify the credentials.
|
Failure Information
But the good details follow below. Using the table from Ultimate Window Security, you can discover why the user login failed. The issues these codes cover go from user name not existing, the user is currently locked out down to domain controller clocks being too far out of sync. Not only is this data useful when helping an end-user, but the data stops you from logging into multiple systems, attempting to discover why the user login failed.
| |
0xC0000064 | User name does not exist. |
xC000006A | User name is correct but the password is wrong. |
0xC0000234 | User is currently locked out |
0xC0000072 | Account is currently disabled |
0xC000006F | User tried to logon outside his day of week or time of day restrictions. |
0xC0000070 | Workstation restriction, or Authentication Policy Silo violation (look for event ID 4820 on domain controller) |
0xC0000193 | Account expiration. |
0xC0000071 | Expired password |
0xC0000133 | Clocks between DC and other computer too far out of sync |
0xC0000244 | User is required to change password at next logon |
0xC0000225 | Evidently a bug in Windows and not a risk |
0xC000015b | The user has not been granted the requested logon type (aka logon right) at this machine |
The Code To Get The Job Done
While all this data is useful, accessing the logs can be a slow process. So at Script Freaks, we have written up a script that will parse out the security logs and return all the correct information, required to not only explain why the user was logged out but break it down in the human-readable form.
$EventLogData = Get-winevent -FilterHashTable @{logname = 'Security'; id = 4625; } #| Sort-Object
Write-Output "Date,Server Name,Username,Failure Message,Logon Type,Source IP,Status Code,Sub Status Code"
foreach ($EventData in $EventLogData) {
$EventMessageVariable = ($EventData.Message -split '\r?\n').Trim()
$DateCreatedVariable = $EventData.TimeCreated | get-date -format "MMddyyyy_HHmms "
$WorkStationNameVariable = $EventMessageVariable[25] -replace 'Workstation Name: ', ''
$AccountNameVariable = $EventMessageVariable[12] -replace 'Account Name: ', ''
$AccountDomainNameVariable = $EventMessageVariable[13] -replace 'Account Domain: ', ''
$FailureReasonVariable = $EventMessageVariable[16] -replace 'Failure Reason: ', ''
$LogonTypeVariable = $EventMessageVariable[8] -replace 'Logon Type: ', ''
$WorkStationIPVariable = $EventMessageVariable[26] -replace 'Source Network Address: ', ''
$StatusVariable = $EventMessageVariable[17] -replace 'Status: ', ''
$SubStatusVariable = $EventMessageVariable[18] -replace 'Sub Status: ', ''
Write-Output "$DateCreatedVariable,$WorkStationNameVariable,$AccountNameVariable,$AccountDomainNameVariable,$FailureReasonVariable,$LogonTypeVariable,$WorkStationIPVariable,$StatusVariable,$SubStatusVariable"
}
Expected Output
Local user failed login output
Comments