Using Powershell to Trace the Source of Account Lockouts in Active Directory

How to: track the source of user account lockout using Powershell

In my last post about how to Find the source of Account Lockouts in Active Directory I showed a way to filter the event viewer security log with a nifty XML query.

In this post I recomposed (Source:Ian Farr) a Powershell script which will ask for the locked user account name and then will scan the active directory DCs security log for relevant events and will present the user lock time and source of the lock out like so:

locked user powershell script

Make sure you have the active directory module loaded on the machine you run the script from: Import-Module ActiveDirectory

You can add the import-module command to the top of the script if you like.

The script:

$ErrorActionPreference = "SilentlyContinue"
Clear-Host

$User = Read-Host -Prompt "Please enter a user name"

#Locate the PDC
$PDC = (Get-ADDomainController -Discover -Service PrimaryDC).Name
#Locate all DCs
$DCs = (Get-ADDomainController -Filter *).Name #| Select-Object name

foreach ($DC in $DCs) {
Write-Host -ForegroundColor Green "Checking events on $dc for User: $user"
    if ($DC -eq $PDC) {
        Write-Host -ForegroundColor Green "$DC is the PDC"
        }
    Get-WinEvent -ComputerName $DC -Logname Security -FilterXPath "*[System[EventID=4740 or EventID=4625 or EventID=4770 or EventID=4771 and TimeCreated[timediff(@SystemTime) <= 3600000]] and EventData[Data[@Name='TargetUserName']='$User']]" | Select-Object TimeCreated,@{Name='User Name';Expression={$_.Properties[0].Value}},@{Name='Source Host';Expression={$_.Properties[1].Value}} -ErrorAction SilentlyContinue
    }

This script scans ALL Domain Controllers and not just the PDC as most people do. I found that sometimes a lockout event will appear in a different DC server, so to make sure you dont miss anything, its better in my opinion to scan all domain controllers and wait the extra time for the script to finish. However, in most cases lockout events will appear on the PDC server.

After you have found the source of user lockout, go to each PC and disconnect the session or look for running scheduled tasks or scripts under this user context.  Rebooting the locking PC if possible, is also a good practice.

Here is another script contributed by Alexandre Almeida on the same topic.

#script written by Alexandre Almeida

# for get user Account Lockout Host name

$username = Read-Host "Please Enter the Locked User Name: "
 
        $DCCounter = 0  
        $LockedOutStats = @()    
                 
        Try 
        { 
            Import-Module ActiveDirectory -ErrorAction Stop 
        } 
        Catch 
        { 
           Write-Warning $_ 
           Break 
        } 
         
        #Get all domain controllers in domain 
        $DomainControllers = Get-ADDomainController -Filter * 
        $PDCEmulator = ($DomainControllers | Where-Object {$_.OperationMasterRoles -contains "PDCEmulator"}) 
         
        Write-Verbose "Finding the domain controllers in the domain" 
        Foreach($DC in $DomainControllers) 
        { 
            # $DCCounter++ 
            # Write-Progress -Activity "Contacting DCs for lockout info" -Status "Querying $($DC.Hostname)" -PercentComplete (($DCCounter/$DomainControllers.Count) * 100) 
      Write-Verbose "Finding the Which domain controllers Authenticate the Password"
            Try 
            { 
                $UserInfo = Get-ADUser -Identity $username  -Server $DC.Hostname -Properties LastLogonDate -ErrorAction Stop 
      Write-Verbose "Bad Password Attempt count collected"
            } 
            Catch 
            { 
                # Write-Warning $_ 
                Continue 
            } 
            If($UserInfo.LastBadPasswordAttempt) 
            {     
                $LockedOutStats += New-Object -TypeName PSObject -Property @{ 
                        Name                   = $UserInfo.SamAccountName 
                        SID                    = $UserInfo.SID.Value 
                        LockedOut              = $UserInfo.LockedOut 
                        BadPwdCount            = $UserInfo.BadPwdCount 
                        BadPasswordTime        = $UserInfo.BadPasswordTime             
                        DomainController       = $DC.Hostname 
                        AccountLockoutTime     = $UserInfo.AccountLockoutTime 
                        LastLogonDate = ($UserInfo.LastLogonDate).ToLocalTime() 
                    }           
            }#end if 
        }#end foreach DCs 
        $LockedOutStats | Format-Table -Property Name,LockedOut,DomainController,BadPwdCount,AccountLockoutTime,LastBadPasswordAttempt -AutoSize 
 
        #Get User Info 
        Try 
        {   
           Write-Verbose "Querying event log on $($PDCEmulator.HostName)" 
     Write-Verbose "Collecting Event Log"
           $LockedOutEvents = Get-WinEvent -ComputerName $PDCEmulator.HostName -FilterHashtable @{LogName='Security';Id=4740} -ErrorAction Stop | Sort-Object -Property TimeCreated -Descending 
        } 
        Catch  
        {           
           Write-Warning $_ 
           Continue 
        }#end catch      
                                  
        Foreach($Event in $LockedOutEvents) 
        {             
           If($Event | Where {$_.Properties[2].value -match $UserInfo.SID.Value}) 
           {  
               
              $Event | Select-Object -Property @( 
                @{Label = 'User';               Expression = {$_.Properties[0].Value}} 
                @{Label = 'DomainController';   Expression = {$_.MachineName}} 
    @{Label = 'EventId';            Expression = {$_.Id}} 
                @{Label = 'LockedOutTimeStamp'; Expression = {$_.TimeCreated}} 
                @{Label = 'Message';            Expression = {$_.Message -split "`r" | Select -First 1}} 
                @{Label = 'LockedOutLocation';  Expression = {$_.Properties[1].Value}}
             ) 
      Write-host $_.MachineName
                                                 
            }#end ifevent 
             
       }#end foreach lockedout event
  Write-Verbose "Collected Details Update in the Text File. Please find the Text file for More Details"

echo "Cache Profile Removal Steps
1) Open Control Panel > Credential Manager > Remove all Saved Password.
2) Remove passwords by clicking on Start => Run => type (rundll32.exe keymgr.dll KRShowKeyMgr) without quotes and then delete the Domain-related passwords;
3) Remove passwords in Internet Explorer => Tools => Internet Options =>Content => Personal Information => Auto Complete => Clear Passwords;
4) Delete cookies in Internet Explorer => Tools => Internet Options =>General;
5) Disconnect (note the path before disconnecting) all networks drives, reboot, then map them again;
6) Start -> run ->type control userpasswords2 without quotes and go to advanced -> Manage passwords and remove all the stored passwords.
7) Reconfigure Your mobile Setting if your Active sync enabled.
8) Check if any saved or scheduled task is configured for user account

Microsoft Kwoledge Bytes Link for Cache profile Removal Steps:

https://social.technet.microsoft.com/Forums/windows/en-US/ced8eab6-87e2-4d20-9d18-7aaf5e9713a3/windows-7-clear-cached-credentials"

 

2 thoughts on “Using Powershell to Trace the Source of Account Lockouts in Active Directory”

  1. i took the liberty to modify the script a little to make a graphic Display of the results and the help information at the end.

    #script written by Alexandre Almeida
    #modified by Roberth Zelaya

    Add-Type -AssemblyName System.Windows.Forms
    Clear-Host

    #ask for elevation if needed
    if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] “Administrator”)) { Start-Process powershell.exe “-NoLogo -WindowStyle hidden -NoProfile -ExecutionPolicy Bypass -File `”$PSCommandPath`”” -Verb RunAs; exit
    }

    $list = Search-ADAccount -lockedout | Select-Object Name, SamAccountName, LastLogonDate, Enabled, DistinguishedName

    $username = $list |select -ExpandProperty SamAccountName

    $DCCounter = 0
    $LockedOutStats = @()

    Try
    {
    Import-Module ActiveDirectory -ErrorAction Stop
    }
    Catch
    {
    Write-Warning $_
    Break
    }

    #Get all domain controllers in domain
    $DomainControllers = Get-ADDomainController -Filter *
    $PDCEmulator = ($DomainControllers | Where-Object {$_.OperationMasterRoles -contains “PDCEmulator”})

    Write-Verbose “Finding the domain controllers in the domain”
    Foreach($DC in $DomainControllers)
    {
    # $DCCounter++
    # Write-Progress -Activity “Contacting DCs for lockout info” -Status “Querying $($DC.Hostname)” -PercentComplete (($DCCounter/$DomainControllers.Count) * 100)
    Write-Verbose “Finding the Which domain controllers Authenticate the Password”
    Try
    {
    $UserInfo = Get-ADUser -Identity $username -Server $DC.Hostname -Properties LastLogonDate -ErrorAction Stop
    Write-Verbose “Bad Password Attempt count collected”
    }
    Catch
    {
    # Write-Warning $_
    Continue
    }
    If($UserInfo.LastBadPasswordAttempt)
    {
    $LockedOutStats += New-Object -TypeName PSObject -Property @{
    Name = $UserInfo.SamAccountName
    SID = $UserInfo.SID.Value
    LockedOut = $UserInfo.LockedOut
    BadPwdCount = $UserInfo.BadPwdCount
    BadPasswordTime = $UserInfo.BadPasswordTime
    DomainController = $DC.Hostname
    AccountLockoutTime = $UserInfo.AccountLockoutTime
    LastLogonDate = ($UserInfo.LastLogonDate).ToLocalTime()
    }
    }#end if
    }#end foreach DCs
    $LockedOutStats | Format-Table -Property Name,LockedOut,DomainController,BadPwdCount,AccountLockoutTime,LastBadPasswordAttempt -AutoSize

    #Get User Info
    Try
    {
    Write-Verbose “Querying event log on $($PDCEmulator.HostName)”
    Write-Verbose “Collecting Event Log”
    $LockedOutEvents = Get-WinEvent -ComputerName $PDCEmulator.HostName -FilterHashtable @{LogName=’Security’;Id=4740} -ErrorAction Stop | Sort-Object -Property TimeCreated -Descending
    }
    Catch
    {
    Write-Warning $_
    Continue
    }#end catch

    $Results =@()

    Foreach($Event in $LockedOutEvents)
    {
    If($Event | Where {$_.Properties[2].value -match $UserInfo.SID.Value})
    {

    $Information = $Event | Select-Object -Property @(
    @{Label = ‘User’; Expression = {$_.Properties[0].Value}}
    @{Label = ‘DomainController’; Expression = {$_.MachineName}}
    @{Label = ‘EventId’; Expression = {$_.Id}}
    @{Label = ‘LockedOutTimeStamp’; Expression = {$_.TimeCreated}}
    @{Label = ‘Message’; Expression = {$_.Message -split “`r” | Select -First 1}}
    @{Label = ‘LockedOutLocation’; Expression = {$_.Properties[1].Value}}
    )
    # Write-host $_.MachineName

    }#end ifevent
    $Results += $Information #add Results to Array for display
    }#end foreach lockedout event

    $display = $Results

    $display | Out-GridView -Title “Lockout information”

    $popUp=[System.Windows.Forms.MessageBox]::Show(“Display Recommendations?” , “Information”,’OKCancel’, “Information”)

    if($popUp-eq “Ok”)
    {
    Display_Information
    }

    function Display_Information()
    {

    $MessageBody = “1) Open Control Panel > Credential Manager > Remove all Saved Password.`n
    2) Remove passwords by clicking on Start => Run => type (rundll32.exe keymgr.dll KRShowKeyMgr) without quotes and then delete the Domain-related passwords;`n
    3) Remove passwords in Internet Explorer => Tools => Internet Options =>Content => Personal Information => Auto Complete => Clear Passwords;
    4) Delete cookies in Internet Explorer => Tools => Internet Options =>General;`n
    5) Disconnect (note the path before disconnecting) all networks drives, reboot, then map them again;`n
    6) Start -> run ->type control userpasswords2 without quotes and go to advanced -> Manage passwords and remove all the stored passwords.`n
    7) Reconfigure Your mobile Setting if your Active sync enabled.`n
    8) Check if any saved or scheduled task is configured for user account.`n
    Microsoft Kwoledge Bytes Link for Cache profile Removal Steps:`n”

    $link=”https://social.technet.microsoft.com/Forums/windows/en-US/ced8eab6-87e2-4d20-9d18-7aaf5e9713a3/windows-7-clear-cached-credentials”

    [System.Windows.Forms.MessageBox]::Show(“$MessageBody” , “Cache Profile Removal Steps”,’OK’, “Information”)

    $validation= $link | Out-GridView -Title “Lockout information” -PassThru

    if($validation -eq $null)
    {
    exit
    }
    else{

    Start-Process($link)
    }
    }

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.