Searching with Event Viewer
Let's see first how you would use the Event Viewer to find an event. To open Event Viewer, navigate to Start, and type "event viewer." When Windows wisely highlights the Event Viewer app, hit Enter. Now, navigate to the log you're seeking. In my case, it's the saved log, "password-spray.evtx".
Filter down to the event log ID you need by clicking Filter Current Log.
Enter the ID or IDs you need to see.
At this point, one of two things will happen. Either you'll do a little scrolling and find the answer to the question you've asked of the log, or you'll do more scrolling than you'd like to admit and realize that there must be a better way to go about this.
You could be staring at thousands, if not tens or hundreds of thousands of events depending on several factors, including how large you allow the given log you're looking at to grow. Furthermore, perhaps the question you're asking isn't so cut and dry. Maybe you're looking for multiple criteria, and you also need certain criteria to be excluded from your results. Scrolling through individual events while trying to find the answer to a very specific question is truly like finding a needle in a haystack, and not a way anyone wants to spend a significant amount of time.
Searching with Get-WinEvent
Instead of the Event Viewer, you can also use the built-in PowerShell cmdlet Get-WinEvent to search the Event Log. Consider the following example:
PS C:\> Get-WinEvent -Path C:\password-spray.evtx |Select-Object -First 1 |Format-List *
This is how the above command works:
- Get-WinEvent: Gets events from Windows event logs.
- -Path: Specifies the location of the log. In addition to using -Path, you can also use -LogName and specify the log you're looking at, such as "Security", to look at the log on the local machine.
- Select-Object -First 1: Show just the first log event.
- Format-List *: Show all the properties of the log event. If we didn't specify this, we'd only see the TimeCreated, ID, LevelDisplayName, and an abbreviated form of the Message properties.
To filter on the ID field, you could use this command:
Get-WinEvent -Path C:\password-spray.evtx |Where-Object -Property Id -eq 4648
However, if you want to limit your search to properties other than the ID, things get complicated with Get-WinEvent because much of the valuable information is stored as text in the event log record, and you would have to work with Regex to retrieve the information you need.
This is where the Convert-EventLogRecord function comes in. In the case of Windows Event ID 4648, it allows you to filter on the following key fields: Subject User SID, Subject Account Name, Subject Domain Name, Subject Logon ID, Subject Logon GUID, Target Account Name, Target Domain Name, Target Logon GUID, Target Server Name, Process ID, Network Address, and Network Port.
Convert-EventLogRecord belongs to the PSScriptTools created by Jeffery Hicks. The function does the heavy lifting for us and parses the data contained in the Message field into individual PowerShell properties. Behind the scenes, it takes the raw Message property, as seen in the output above, converts it to XML, and then creates new and properly parsed data properties.
The command is identical to the previous example, except for adding in Convert-EventLogRecord. We'll be passing that one log entry for it to go ahead and parse. Then with Format-List *, we'll again look at all its output.
PS C:\> Get-WinEvent -Path C:\password-spray.evtx | Select-Object -First 1 | Convert-EventLogRecord |Format-List *
Hopefully, the above output is as magical for you as it was for me the first time I used Jeffery Hicks' tool.
Now that we are able to parse on all this rich telemetry, I'm going to round out this article with a query that could help us identify a password spraying attack in the Windows Security log.
If you aren't familiar with password spray attacks and why we would want to identify them, here’s the reason. Password spray attacks allow an attacker to figure out a target user's credentials even in environments with password lockout policies in place. They do this not by using brute force on one user's password with many commonly used passwords (and subsequently locking the user out after maybe four attempts), but by targeting many users' passwords with the most commonly used passwords.
For example, does “Spring2021!” look familiar? It would pass most complexity and length requirements and is also very easy to remember and update every quarter; hence, the reason so many people might use a password like this. Attackers know these passwords and also know that there will be some users who will use them.
Here's what we'll do in the final example:
- Get-WinEvent -Path C:\password-spray.evtx: Get our password-spray.evtx log Windows events.
- Where-Object -Property Id -eq 4648: Filter on only event ID 4648. The description for this event from Microsoft is "A logon was attempted using explicit credentials." It's commonly seen during password spraying attacks.
- Convert-EventLogRecord: Convert the event log data to fully parsed properties.
- Group-Object IpAddress,SubjectUsername,TargetUsername –NoElement: Group the events that all have matching IP Addresses, Subject Usernames, and Target Usernames with Group-Object, and don't show additional data with –NoElement. This command simultaneously elevates attempts with shared IP addresses, Source Usernames, and Target Usernames, and also makes attempts having unique Target Usernames stand out.
- Format-Table -AutoSize: Lastly, format the results into a table and show the complete output of each.
PS C:\> Get-WinEvent -Path C:\password-spray.evtx | Where-Object -Property Id -eq 4648 |Convert-EventLogRecord |Group-Object IpAddress,SubjectUsername,TargetUsername -NoElement |Format-Table -AutoSize
Depending on the volume of your dataset, you may need to filter and parse differently, but using the Group-Object cmdlet enables us to group similar patterns and bubble the patterns that have the most hits to the top with default count sorting. So in this albeit very limited case, we can quickly see that the same source IP address and source username are attempting to authenticate against many different target usernames. This would certainly be cause for suspicion and worth investigating further.
Hopefully, this article gave you a good introduction to more advanced Windows event log analysis using both PowerShell and Jeffery Hicks' Convert-EventLogRecord cmdlet and a taste of how you can leverage those tools to do security-related Windows event log analysis in your environment.
Subscribe to 4sysops newsletter!
Note: The examples that I show in this article are from the security event log file hosted here. You can download the same file and follow along yourself. Thanks to Eric Conrad and Joshua Wright for both DeepBlueCLI and this example event log file.
Join the 4sysops PowerShell group!
Your question was not answered? Ask in the PowerShell forum!
I’ve set up Windows Event Forwarding (50 servers that send logs to 1 collector) and this just made my work a lot easier.
Thanks and keep up the good work