Tracking down account lockout sources with PowerShell

On This Page

Update: I had a question about checking other DCs beyond just the PDC, according to Microsoft:

Account lockout is processed on the PDC emulator.

I can’t say for certain that account lockouts will always happen on the PDC and no where else, but in a perfect world that should hold true.

Original post:

One very frustrating task to accomplish for a sysadmin is tracking down why an account has been locked out. Especially when a user asks you to unlock their account 2 minutes after the last time they asked. It is clearly your fault, definitely not the fact that they never changed the password on their iPad that is syncing with Exchange. The good news is that even though it can take a bit of time to filter through logs, if you do some leg work ahead of time with PowerShell we can cut down the time to a few seconds.

Background

Before we dive into building the tool, I want to make sure we are on the same page.

The event

Whenever an account is lockedout, EventID 4740 is generated on the authenticating domain controller and copied to the PDC Emulator. Inside that event, there are a number of useful bits of information. Obviously the date, time, and account that was locked out, but it also includes information about where the lockout originated from. Specifically the Caller Computer as it calls it, and we can grab all of that information with PowerShell!

The command

To retrieve event logs from a remote computer that allows remote event log management, we’ll use the Get-WinEvent cmdlet. At a bare minimum, we need to include the logname that we are querying. In this case, the security log:

Get-WinEvent -LogName Security

That’ll list out all the recent events in the security log.

Building a tool

So now that we have all of that information, lets build ourselves a tool to do the work for us!

Filtering to the left

In PowerShell, the further you can filter to the left, the more efficient your commands will be. In this specific instance, we can use the Get-WinEvent cmdlet to filter for certain event IDs in a certain log using the -FilterHashtable parameter. To find account lockouts, this would look like:

Get-WinEvent -FilterHashtable @{
LogName ='Security'
ID = 4740
}

Or if we were running this remotely, we’d need to find the PDC Emulator first:

Because the second example returns all the events and passes them down the pipeline to be filtered by Where-Object. But hey, you definitely shouldn’t believe me just because I say that, lets run some tests:

This took half a second. That is 1/1600 the amount of time. That is why you should filter to the left whenever possible.

The event object

My apologies for the sidetrack, that is important info! Lets take a look at the event object that gets returned as well. It has the expected metadata such as a timestamp, ID, level, and message. If we take a look at the message property, we see something like:

That is pretty sweet! We get to see the account that was locked out and where it came from. Though, believe it or not, I’m not going to recommend regex here. The event object also has another property: properties:

So we don’t even need to worry about parsing the string, we just need to know what index each property is.

Looping for all events

The last step, before finalizing this with a function, is to loop through each event and create the appropriate output object. I’ll choose to do that with a foreach loop and create a custom object to format the output:

There’s a lot you can do! And this will save you time over manually searching the event viewer, trust me.

Conclusion

I hope this has been helpful for you! This is a tool that I have use many times and easily impressed callers during my time on the helpdesk when I was quickly able to tell them why they were being locked out.

Be sure to check out my other posts here on my blog and the other tools I’ve got in my Utilities repository.

If you got feedback, leave me a comment, tweet at me, send me an email, whatever works for you!