Home Digging in to EventID 4625
Post
Cancel

Digging in to EventID 4625

Using event logs to determine whether an attack is possible has been used by blue and red teams alike. Several hacking groups such as turla have been using antivirus logs to determine whether their payloads were successful and for most red team engagements, pentesters use logs to debug their payloads. This can be essential when attempting to run successful phishing campaigns, finetune lateral movement techniques, and ensure that evasion techniques are able to bypass the relevant software in use throughout an organisation.

Recently, I have been looking into Windows event logs and I was curious as to whether it would be possible to use the Status codes returned by Windows during logon events to enumerate successful username/password combinations. This post is going to cover the following:

  1. A look at how I investigated Error Codes returned by EventId 4625
  2. A hypothetical situation for password enumeration through the use of log files and status codes

Diving into EventId 4625

I was looking into ways to bruteforce Active Directory Username/Password fields. In order to determine what was possible, I decided to look into the logon events generated during authentication to see if there was anything that suggested that you could enumerate usernames or passwords without getting the generic “Username/Password is incorrect” error message. In order to generate failed logon attempts within my small test domain, I initially used impacket’s wmiexec with the following command:

1
python wmiexec.py corp/administraotr@192.168.56.2

When retrieving the logs, you can use the Get-EventLog PowerShell module. The command shown below returns the information associated with the most recent event failed logon attempt:

1
Get-EventLog -LogName Security -InstanceId 4625 -Newest 1 | Select-Object -Property *

Event logs contain an abundance of useful information, the screenshot below shows an excerpt of the information generated by the aforementioned failed logon attempt:

As shown above, the Failure Information section contains 2 failure codes:

  1. Status
  2. Sub Status

The status code that was returned by the failed logon event with wmiexec was the generic version 0xc000006d which correlates to “This is either due to a bad username or authentication information”. The part that caught my attention however, was the Sub Status code which contained more detailed information, specifically 0xc0000064 which correlates to “User logon with misspelled or bad user account”.

Based on this information, if there was a way to retrieve the Sub Status code remotely while attempting to authenticate to the domain, you would be able to enumerate user credentials. While this might not be super relevant for bruteforcing, it would allow you to confirm whether any previously identified user credentials were valid, or which part of the username/password combination was incorrect.

Attempt 1 - Using WMIEXEC on Linux

As stated before, I attempted to authenticate initially using wmiexec. While authenticating, I ran Wireshark (a network protocol analyzer) and found that the network traffic included the Status code, but I wanted to see if the Sub Status code was returned at any point. Diving into the NT Status: STATUS_LOGON_FAILURE (0xc000006d) error produced the following:

Once again, I could only find the generic Status code: 0xc000006d, and the Sub Status code was not returned at any point.

Attempt 2 - Using Runas on Windows

Since I did not find a way to retrieve the Sub Status code using Linux, I decided to see if it would be possible to retrieve any additional information using a Windows machine. In order to generate these logon events, I used the following Runas command:

1
runas /profile /env /user:corp\Alice cmd.exe

While running this command, I did not make use of the netonly flag because I wanted the command to authenticate against the domain controller. An excerpt from the log file is shown below:

As with the failed logon event generated with wmiexec, the generic Status code 0xc000006d which correlates to “This is either due to a bad username or authentication information” was created. In this instance a bad password was supplied during the authentication attempt and the Sub Status code 0xc000006a which correlates to “User logon with misspelled or bad password” was created.

While looking at the RUNAS ERROR, a default error message for incorrect logon via the runas command was returned as shown below:

1
2
RUNAS ERROR: Unable to runcmd.exe
1326: The user name or password is incorrect.

While using runas, as with wmiexec, I ran Wireshark. Looking into the WireShark output, the error returned was in the form of Kerberos Error Codes.

The Kerberos documentation for eRR-PREAUTH-FAILED (24) only provided us with the generic version “Pre-authentication information was invalid” as alluded to by the Microsoft codes. As with the Linux instance, the Sub Status code was not returned at any point. If you would like to dig deeper into the Wireshark output generated by Kerberos, Kerberos Wireshark Capture: A Windows Login Example provides a great breakdown of the network traffic captured during user authentication.

Quick note on accessing log files

Throughout this blogpost, it was assumed that you would be able to access the log files. If you have the required permissions, you will be able to access the logs remotely using the following command:

1
Get-EventLog -LogName Security -ComputerName DC01 -InstanceId 4625 -Newest 1

In general it looks like you would need to have elevated privileges (e.g. Local Admin) on the host, otherwise an error similar to the one shown below will be returned:

Password Enumeration using Log Files

Although it makes sense that you aren’t able to just retrieve the error codes through network traffic, the scenario I see that could work is described below:

  • Step 1: Gain access to an account with the required permissions in order to view the log files ,e.g. Local Admin, SYSTEM, etc.
  • Step 2: Attempt to authenticate to either your host or another host with the credentials you are testing.
  • Step 3: Retrieve the Event logs and investigate the Sub Status code.
  • Step 4: Use this code to determine why the new credentials are not working - e.g. Wrong username/password/cannot access computer, etc.

Obviously this wouldn’t be efficient at all, and there are a number of ways that you can do this without going through the effort of looking in to log files. Additionally, if you have the permissions required to open the log files, then you can more than likely find easier ways to enumerate usernames (e.g. running BloodHound). While this post doesn’t provide any new ways on enumerating user credentials within a Windows environment, it was fun looking into the event logs for failed logon attempts and using the time to figure out why enumeration was not possible.

From a defensive point of view, the retrieval of the Sub Status codes could be useful when trying to determine if bruteforce attacks against specific usernames are occurring. If you read up until this point, I hope you learnt something new about event logs or failed logon attempts!

This post is licensed under CC BY 4.0 by the author.