Поиск источника блокировки пользователя в Active Ditectory

в 13:05, , рубрики: microsoft, powershell, системное администрирование, метки:

В работе администратора домена Active Directory довольно часто возникает необходимость найти причину блокировки пользователя. Иногда причиной блокировки пользователя является заражённый вирусом ПК — в таких случаях особо важна скорость обнаружения источника проблемы. В PowerShell 2 на Windows 2008 R2 есть прекрасный командлет Get-WinEvent который позволяет решать данную задачу за 1-2 минуты даже в очень большом домене.
Примечание: всё далее описанное касается только PowerShell >= 2.0

Необходимые исходные условия.

Да, чудес не бывает, и для поиска причины блокировки пользователей потребуется некоторая настройка аудита безопасности на контроллерах домена. Должны быть включены следующие подкатегории аудита на контроллерах домена:

Категория аудита Подкатегория аудита Тип аудита Интересующий нас eventID
Audit Account Logon Events (Вход учётной записи) Kerberos Authentication Service (Аудит службы проверки подлинности Kerberos) Отказ 4771 Kerberos pre-authentication failed.
Audit Logon Events (Вход/Выход) Logon (Аудит входа в систему) Отказ 4625 An account failed to log on.
Audit Logon Events (Вход/Выход) Account Lockout (Аудит блокировки учётных записей) Успех 4740 Account locked
Алгоритм поиска источника блокировки

  1. Определить какой контроллер является владельцем роли PDC-эмулятора
  2. Найти в журнале безопасности PDC-эмулятора событие с кодом 4740 в поле «TargetUserName», которого указано имя интересующего нас пользователя
  3. В поле «TargetDomainName» того же события найти имя контроллера домена, обслужившего авторизацию
  4. Найти в журнале безопасности контроллера, обслужившего авторизацию, событие с кодом 4625 (неуспешная NTLM авторизация) или 4771 (неуспешная kerberos авторизация)
  5. Из найденного события получить значения полей «IpAddress» — адрес ПК с которого была попытка авторизации

Этих действий будет достаточно для быстрого поиска ПК с вредоносным ПО, подбирающим пароли пользователей. Как правило достаточно быстро вычислить источник проблемы и изолировать его для дальнейшего расследования. Алгоритм поиска процесса непосредственно вызывающего блокировку пользователя сильно зависит от ПО, установленного на конечном ПК.

Используемые командлеты PowerShell

  • Get-ADDomainController — для определения владельца роли PDC-эмулятора
  • Get-WinEvent — «волшебный» командлет, благодаря которому и стал возможным быстрый поиск

В чём «магия» Get-WinEvent?
Во-первых он ищет события с конца и имеет параметр -MaxEvents, позволяющий найти только самое последнее событие или неколько самых последних событий.
Во-вторых он имеет прекрасный параметр -FilterHashtable, который позволяет очень гибко задать условия поиска события.

Скрипт поиска

Для себя я подготовил небольшой PowerShell скрипт.
На входе скрипт принимает либо имя пользователя, для которого необходимо найти источник блокировки, либо количество (по умолчанию — 1) последних заблокированных пользователей.

 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

Пример использования:

PS> Find-Locker.ps1 -User i.i.inanov
PS> Find-Locker.ps1 -Count 10
Вместо P.S.

Да, есть Account Lockout and Management Tools с прекрасной утилитой LockoutStatus.exe, но она долго опрашивает все контроллеры домена (а некоторый из них могут быть и недоступны).
Предложенный скрипт никак не претендует на замену LockoutStatus.exe (у них совершенно разный принцип работы). Обычно я использую их вместе.

Готовый скрипт можно скачать с Google Drive: Find-Locker.ps1

Автор: Slipeer

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js