📜 ⬆️ ⬇️

Search for the user's blocking source in Active Ditectory

In the work of an Active Directory domain administrator, quite often there is a need to find the reason for blocking a user. Sometimes the reason for blocking a user is a PC infected with a virus - in such cases, the speed of detecting the source of the problem is particularly important. In PowerShell 2 on Windows 2008 R2 there is an excellent Get-WinEvent cmdlet that allows you to solve this problem in 1-2 minutes even in a very large domain.
Note: all further described concerns only PowerShell> = 2.0

Necessary initial conditions.

Yes, there is no miracle, and to find the reason for blocking users, some configuration of security auditing on domain controllers will be required. The following audit subcategories on domain controllers should be included:
Audit categoryAudit subcategoryAudit typeEventID of interest
Audit Account Logon EventsKerberos Authentication Service (Kerberos Authentication Service Audit)Renouncement4771 Kerberos pre-authentication failed.
Audit Logon Events (Login / Logout)Logon (Login Audit)Renouncement4625 An account failed to log on.
Audit Logon Events (Login / Logout)Account Lockout (Audit Account Lockout)Success4740 Account locked


The search algorithm for the source of the lock

  1. Determine which controller owns the role of the PDC emulator
  2. Find the event 4740 in the “TargetUserName” field in the security log of the PDC emulator with the name of the user that interests us
  3. In the field “TargetDomainName” of the same event find the name of the domain controller that served the authorization
  4. Find in the security log of the controller that served the authorization an event with the code 4625 (unsuccessful NTLM authorization) or 4771 (unsuccessful kerberos authorization)
  5. From the event found, get the values ​​of the “IpAddress” fields - the address of the PC from which the authorization was attempted


This will be enough to quickly find a PC with malware picking up user passwords. As a rule, quickly enough to calculate the source of the problem and isolate it for further investigation. The process search algorithm of the user directly blocking is highly dependent on the software installed on the target PC.
')
Used PowerShell cmdlets



What is the "magic" of Get-WinEvent?
First, it searches for events from the end and has the -MaxEvents parameter, which allows you to find only the most recent event or some of the most recent events.
Secondly, it has an excellent -FilterHashtable parameter that allows you to set the event search conditions in a very flexible way.

Search script

For myself, I prepared a small PowerShell script.
At the entrance, the script accepts either the name of the user for whom the blocking source is to be found, or the number (by default - 1) of the last blocked users.
param ( $User, $Count = 1 ) $result = New-Object system.Data.DataTable "Locks" $col1 = New-Object system.Data.DataColumn Username,([string]) $col2 = New-Object system.Data.DataColumn DCFrom,([string]) $col3 = New-Object system.Data.DataColumn LockTime,([string]) $col4 = New-Object system.Data.DataColumn eventID,([string]) $col5 = New-Object system.Data.DataColumn SourceHost,([string]) $col6 = New-Object system.Data.DataColumn LogonType,([string]) $col7 = New-Object system.Data.DataColumn LogonProcessName,([string]) $col8 = New-Object system.Data.DataColumn FalureTime,([string]) $result.columns.add($col1) $result.columns.add($col2) $result.columns.add($col3) $result.columns.add($col4) $result.columns.add($col5) $result.columns.add($col6) $result.columns.add($col7) $result.columns.add($col8) $PDC = [string](Get-ADDomainController -Discover -Service PrimaryDC).Hostname $FilterHash = @{} $FilterHash.LogName = "Security" $FilterHash.ID = "4740" if ($User) { $FilterHash.data =$User $Count = 1 } $FilterHash2 = @{} $FilterHash2.LogName = "Security" $FilterHash2.ID = @("4625", "4771") Get-WinEvent -Computername $PDC -FilterHashtable $FilterHash -MaxEvents $Count | foreach { $Row = $result.NewRow() $Username = ([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “TargetUserName”} | %{$_."#text"} $DCFrom = ([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “TargetDomainName”} | %{$_."#text"} $LockTime = $_.TimeCreated $FilterHash2.data = $username Get-WinEvent -Computername $dcfrom -FilterHashtable $FilterHash2 -MaxEvents 3 | foreach { $Row = $result.NewRow() $Row.Username = $Username $Row.DCFrom = $DCFrom $Row.LockTime = $LockTime $Row.eventID = $_.ID $Row.SourceHost = ([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “IpAddress”} | %{$_."#text"} $Row.LogonType = ([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “LogonType”} | %{$_."#text"} switch ($Row.LogonType) { "2" {$Row.LogonType = "Interactive"} "3" {$Row.LogonType = "Network"} "4" {$Row.LogonType = "Batch"} "5" {$Row.LogonType = "Service"} "7" {$Row.LogonType = "Unlock"} "8" {$Row.LogonType = "NetworkCleartext"} "9" {$Row.LogonType = "NewCredentials"} "10" {$Row.LogonType = "RemoteInteractive"} "11" {$Row.LogonType = "CachedInteractive"} } $Row.LogonProcessName = ([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “LogonProcessName”} | %{$_."#text"} $Row.FalureTime = $_.TimeCreated $result.Rows.Add($Row) } } $result | Format-Table -AutoSize 


Usage example:
 PS> Find-Locker.ps1 -User iiinanov PS> Find-Locker.ps1 -Count 10 


Instead of ps

Yes, there are Account Lockout and Management Tools with the excellent LockoutStatus.exe utility, but it polls all domain controllers for a long time (and some of them may not be available).
The proposed script does not pretend to replace LockoutStatus.exe (they have a completely different principle of operation). I usually use them together.

The finished script can be downloaded from Google Drive: Find-Locker.ps1

Source: https://habr.com/ru/post/171701/


All Articles