Keeping track of locked out accounts is important. Furthermore it can be important to know where and when an account was locked out. For instance the source of the lockout can be important to know if one of your users is complaining that his account is being locked but he doesn’t know why.
This script scans the event log of your DC and gets all lockout events and then exports them to a CSV. If you run this script regularly with the task scheduler you can document all locked out accounts along with the time and source of the lockouts.
I have split the script into three sections variables, functions and script main.
Variables
#VARIABLES $scriptpath = $MyInvocation.MyCommand.Path $dir = Split-Path $scriptpath #path to the directory from which the script is run. $after = (get-date).addHours(-1) #time back to search the event log $lockoutEventID = 4740 #event id of lockout #parameters $DC = "SomeDC" #Name of domain controller to scan event logs on
It is important to remember to enter the name of your DC in $DC in the parameters section. The rest can be left as is.
Functions
1. Function Get-LockoutEvents
function Get-LockoutEvents { param( $after, $lockoutEventID, $computerName = $env:COMPUTERNAME ) $lockoutEvents = @(Get-EventLog -LogName "Security" -After $after -ComputerName $computerName | Where-Object {$_.EventID -eq $lockoutEventID}) return $lockoutEvents }
Get-LockoutEvents uses the powershell cmd-let Get-EventLog to scan the event log on the specified computer $computerName (should be a domain controller). It then returns an array containing the events found.
2. Function Parse-LockoutEvent
function Parse-LockoutEvent { param( $lockoutEvent ) $EventTxt = $lockoutEvent.Message $bool = $EventTxt -match "(.*?)(Account That Was Locked Out:)[\S\s]+Account Name:[\s]+?(\w+)" $lockoutUser = $Matches[3] $lockoutTime = $lockoutEvent.TimeGenerated $lockoutSource = $lockoutEvent.Source $lockoutMessage = $lockoutEvent.Message -creplace "`n|`r","" $lockoutMessage = $lockoutMessage -creplace "`t"," " $lockout = "" | select "User","Time","Source","Message" $lockout.User = $lockoutUser $lockout.Time = $lockoutTime $lockout.Source = $lockoutSource $lockout.Message = $lockoutMessage Return $lockout }
This function takes a lockout event as a parameter and parses the most relevant parts to readable information. It returns a custom object with four properties user, time, source and message. User is the locked out user account. Time is the time of the lockout. Source is the entity which locked out the account. Message is the message text of the event which also normally includes the name/IP of where the account was locked out (in other words where the bad passwords were entered).
3. ExportToFile-LockoutEvents
function ExportToFile-LockoutEvents { param( $lockouts ) $datestr = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" $fileName = "$dir\Lockouts--$datestr.csv" $lockouts | Export-Csv $fileName -NoTypeInformation }
This little function simply takes an array of parsed lockoutevents and exports it to a CSV file with a time stamp.
Script Main
#SCRIPT MAIN $lockouts = @() $lockoutEvents = Get-LockoutEvents -after $after -lockoutEventID $lockoutEventID if ($lockoutEvents) { $lockoutEvents | % { $lockout = Parse-lockoutEvent -lockoutEvent $_ $lockouts += @($lockout) } $lockouts #print the lockout events to the console ExportToFile-LockoutEvents -lockouts $lockouts #export the lockout events to CSV }
In the script main I start by creating the blank array $lockouts. I then use the function Get-LockoutEvents to get the information and store it in another object called $lockoutEvents. If any lockout events were found they are parsed and then added to the array $lockouts which is then exported to a CSV file (and printed to the console window).
I have copied in the full script below. Enjoy!
################################################################################################################## ##Script: Get-LockedOutAccounts.ps1 ##Description: Script gets lockout events from the event log and parses them before exporting to CSV. ##Usage: ##Created by: Noam Wajnman ##Creation Date: March 5, 2014 ################################################################################################################### #VARIABLES $scriptpath = $MyInvocation.MyCommand.Path $dir = Split-Path $scriptpath #path to the directory from which the script is run. $after = (get-date).addHours(-1) #time back to search the event log $lockoutEventID = 4740 #event id of lockout #parameters $DC = "SomeDC" #Name of domain controller to scan event logs on #FUNCTIONS function Get-LockoutEvents { param( $after, $lockoutEventID, $computerName = $env:COMPUTERNAME ) $lockoutEvents = @(Get-EventLog -LogName "Security" -After $after -ComputerName $computerName | Where-Object {$_.EventID -eq $lockoutEventID}) return $lockoutEvents } function Parse-LockoutEvent { param( $lockoutEvent ) $EventTxt = $lockoutEvent.Message $bool = $EventTxt -match "(.*?)(Account That Was Locked Out:)[\S\s]+Account Name:[\s]+?(\w+)" $lockoutUser = $Matches[3] $lockoutTime = $lockoutEvent.TimeGenerated $lockoutSource = $lockoutEvent.Source $lockoutMessage = $lockoutEvent.Message -creplace "`n|`r","" $lockoutMessage = $lockoutMessage -creplace "`t"," " $lockout = "" | select "User","Time","Source","Message" $lockout.User = $lockoutUser $lockout.Time = $lockoutTime $lockout.Source = $lockoutSource $lockout.Message = $lockoutMessage Return $lockout } function ExportToFile-LockoutEvents { param( $lockouts ) $datestr = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" $fileName = "$dir\Lockouts--$datestr.csv" $lockouts | Export-Csv $fileName -NoTypeInformation } #SCRIPT MAIN $lockouts = @() $lockoutEvents = Get-LockoutEvents -after $after -lockoutEventID $lockoutEventID if ($lockoutEvents) { $lockoutEvents | % { $lockout = Parse-lockoutEvent -lockoutEvent $_ $lockouts += @($lockout) } $lockouts #print the lockout events to the console ExportToFile-LockoutEvents -lockouts $lockouts #export the lockout events to CSV }