How To Find Failed Logon Attempts in PowerShell

Brien Posey

December 5, 2022

4 Min Read
How To Find Failed Logon Attempts in PowerShell
Alamy

Anyone who has ever sifted through the Windows Event Viewer knows just how many log entries Windows tends to generate. It’s easy to overlook something important.

While there are certainly good third-party tools that can help with this, you can also use PowerShell to track down event log entries. The advantage to using PowerShell for such tasks is that not only does it make it easier to find exactly what you are looking for, but you can even script actions that will run if certain events have occurred.

In this article, I want to show you how to use PowerShell to find failed logon attempts.

Before I Get Started

There are two things to note. First, even though I will focus on failed logons, the technique that I discuss can be adapted to work with any event log entry. Second, this technique is not designed for real-time detection of failed logons. Instead, it’s primarily designed to keep you aware of what is going on within your network. Again, there are some good third-party security tools that can alert you to failed logons in real time.

The Windows event logs assign an Event ID to each type of event that is logged. The Event ID used for a failed logon attempt is 4625. Similarly, Event ID 4624 reflects a successful logon. That being the case, the way to go about tracking down failed logons is to build a simple PowerShell script that searches the event logs for instances of Event ID 4625.

Related:Why Security Logging Is Key to Ransomware Response

At its simplest, such a script might look like this:

Get-WinEvent -FilterHashTable @{LogName="Security"; ID=4625} | Select-Object TimeCreated, Message | Format-Table -Wrap

Get-WinEvent is the PowerShell cmdlet used to retrieve the Windows event logs. The trick to extracting information from the logs is to treat them as a hash table. Doing so gives you the ability to filter log entries on an as-needed basis. In this case, we are using the LogName=”Security” filter to make it so that only events from the Windows Security logs are returned. We are also using the ID=4625 filter to ensure that only instances of Event ID 4625 are returned.

As you can imagine, there can be a lot of information associated with an event log entry. For a 4625 event, the logs contain information such as the ID associated with the thread and process that triggered the event. You can also see the name of the computer, the user ID, the time when the event was created, and more.

If you look back at the command that I used, you can see that I used the Select-Object cmdlet to display the time when the event was created and the event message. While it might seem that limiting the output in this way would diminish the value of the results, the message that is associated with Event 4625 contains a lot of information. In fact, the sheer volume of information that is being produced is the reason why the command ends in Format-Table -Wrap. Without this command, the output would be truncated. You would see that a logon failure had occurred, but the message wouldn’t tell you anything useful. You can see an example of this in Figure 1.

PowerShell screenshot shows truncated output with a message that says

Failed logon 1

Figure 1. This is what happens if you do not wrap the output.

In contrast, appending Format-Table -Wrap causes PowerShell to produce very verbose information that may be highly useful. You can see a portion of that output in Figure 2.

PowerShell screenshot shows portion of output when appending Format-Table -Wrap

Failed logon 2

Figure 2. PowerShell can provide a wealth of information about failed logon attempts.

In a production environment, it is entirely possible that you will have a large number of 4625 events, so it may be useful to adjust your filter to reduce the number of results and zero in on what you are truly interested in. Figure 3 shows a list of the properties that you can filter by (excluding the message). In case you are wondering how I got this list, I changed the Select-Object portion of the command to say Select-Object *, thereby revealing all the log properties.

PowerShell screenshot shows a list of the properties that you can filter by (excluding the message)

Failed logon 3

Figure 3. These are some of the properties that you can use in your filter.

You can use any of these attributes as filters. For example, if you wanted to filter by machine name, you would modify the command to look like this:

Get-WinEvent -FilterHashTable @{LogName="Security"; ID=4625; MachineName=”Win-CFVP7ABN07K”} | Select-Object TimeCreated, Message | Format-Table -Wrap

Keep in mind that I am referencing a specific machine name, so you should substitute the machine name that you want to query. Similarly, you can filter the output by date. If you want to see all the events that have occurred in the last day, you could use this command:

$Start=(Get-Date).AddDays(-1)Get-WinEvent -FilterHashTable @{LogName="Security"; ID=4625;StartTime=$Start} | Select-Object TimeCreated, Message | Format-Table -Wrap

About the Author

Brien Posey

Brien Posey is a bestselling technology author, a speaker, and a 20X Microsoft MVP. In addition to his ongoing work in IT, Posey has spent the last several years training as a commercial astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space.

https://brienposey.com/

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like