Gather Bad Password Attempts and Account Lockout Info in PowerShell

If a user account gets locked out, I can follow these tips to find out why and when it happened. But how can I check and gather lockout info along with the bad password attempts info of all users across the entire AD domain?

Asking help from PowerShell is my answer.

There are two places where we can gather this information. The AD contains the bad password attempts and the lockout status while the security event log saves the user account lockout information when it happens.

To get bad password attempts info from AD, use Get-ADUser cmdlet.

Get-ADUser -Filter * -Properties AccountLockoutTime,LastBadPasswordAttemptBadPwdCount,LockedOut

If you want just the info for the past day, pipe the result to Where clause.

Get-ADUser -Filter * -Properties AccountLockoutTime,LastBadPasswordAttemptBadPwdCount,LockedOut | Where {$_.LastBadPasswordAttempt -gt (Get-Date).AddDays(-1)}

To get the account lockout info, use Get-EventLog cmd to find all entries with the event ID 4740. Use -After switch to narrow down the date.

Get-EventLog -LogName "Security" -ComputerName "AD_Server" -After (Get-Date).AddDays(-1) -InstanceID "4740" | Select TimeGenerated, ReplacementString

Depending on the size of the log file, it could take a while to get all the result.

Going through the result, you may find the data shown on the screen is incomplete. That’s because the ReplacementString is a string array that contains the event log data in an XML type of format. Each event type has its own string structure. For 4740 events, 

  • ReplacementString[0] stores the name of the computer where the account gets locked out and
  • ReplacementString[1] indicates the name of the user account that gets locked out.

So, instead of running the above cmdlet, the following script provides a lot more clear useful info.

#Collect lockout accounts from ADS
$logname = "security"
$dcname = (Get-AdDomain).pdcemulator
$eventID = "4740"
$content = Get-EventLog -LogName $logname -ComputerName $dcname -After (Get-Date).AddDays(-1) -InstanceId $eventID | Select TimeGenerated, ReplacementStrings
$ofs = "`r`n`r`n"
$body = "Fetching event log started on " + (Get-Date) + $ofs
If ($content -eq $null)
$body = $body + "No lock-out accounts happened today" + $ofs
Foreach ($event in $content)
$source = $content.ReplacementStrings[1]
$username = $content.ReplacementStrings[0]
$body = $body + $event.TimeGenerated + ": " + $username + " - " + $source + $ofs

Hope it helps.

Leave a Reply

Your email address will not be published. Required fields are marked *