Есть несколько различных инструментов получения информации о времени логина пользователя в домен. Время последней успешной аутентификации пользователя в домене можно получить из атрибута lastLogon (обновляется только на контроллере домена, на котором выполнена проверка учетных данных пользователя) или lastLogonTimpestamp (реплицируется между DC в домене, но по умолчанию только через 14 дней). Вы можете получить значение этого атрибута пользователя в редакторе атрибутов AD или командлетом Get-ADUser. Однако иногда нужно получить историю активности (входов) пользователя в домене за большой период времени.
Вы можете получить информацию об успешных входах (аутентфикации) пользователя в домене из журналов контроллеров домена. В этой статье мы покажем, как отслеживать историю входов пользователя в домен с помощью PowerShell.. Т.е. можно получить полную историю активности пользователя в домене, время начала работы и компьютеры, с которых работает пользователь.
Политика аудита входа пользователя в домен
Чтобы в журналах контроллеров домена отображалась информация об успешном/неуспешном входе в систему, нужно включить политику аудита событий входа пользователей.
- Запустите редактор доменных GPO – GPMC.msc;
- Откройте настройки Default Domain Policy и перейдите в раздел Computer Configuration -> Policies -> Windows Settings -> Security Settings –> Advanced Audit Policy Configuration -> Audit Policies -> Logon/Logoff;
- Включите две политики аудита (Audit Logon и Audit Other Logon/Logoff Events). Чтобы в журналах Security на DC и компьютерах регистрировались как успешные, так и неуспешные политики входа, выберите в настройках политика аудита опции Success и Failure
- Сохраните изменения в GPO и обновите настройки политик на контроллерах домена командой:
gpupdate /force
(или подождите 90 минут, без учета репликации между DC).
Теперь при входе пользователя на любой компьютер домена Active Directory в журнале контроллера домена, который выполняет аутентификацию пользователя, появляется событие с Event ID 4624 (An account was successfully logged on). В описании этого события указана учетная запись, которая успешно аутентифицировалась (Account name), имя (Workstation name) или IP адрес (Source Network Address) компьютера, с которого выполнен вход.
Также в поле Logon Type указан тип входа в систему. Нас интересуют следующие коды
- Logon Type 10 – Remote Interactive logon – вход через службы RDP, теневое подключение или Remote Assistance (на DC такое событие может быть при входе администратора, или другого пользователя, которому предоставлены права входа на DC) Это событие используется при анализе событий входа пользователей по RDP.
- Logon Type 3 – Network logon сетевой вход (происходит при аутентфикации пользователя на DC, подключения к сетевой папке, принтеру или службе IIS)
Также можно отслеживать событие выдачи билета Kerberos при аутентификации пользователя. Event ID 4768 — A Kerberos authentication ticket (TGT) was requested. Для этого нужно включить аудит событий в политики Account Logon –> Audit Kerberos Authentication Service -> Success и Failure.
В событии 4768 также указана учетная запись пользователя (Account Name или User ID), который получил билет Kerberos (аутентифицировался) и имя (IP адрес) компьютера.
PowerShell: истории сетевых входов пользователя в домен
С помощью командлета PowerShell Get-Eventlog можно получить все события из журнала контроллера домена, отфильтровать их по нужному коду (EventID) и вывести данные о времени, когда пользователь аутентифицировался в домене, и компьютере, с которого выполнен вход. Т.к. в домене может быть несколько контроллеров домена и нужно получить история входов пользователя с каждого из них, нужно воспользоваться командлетом Get-ADDomainController (из модуля AD для Windows PowerShell). Данный командлет позволяет получить список всех DC в домене.
Следующий PowerShell скрипт позволяет получить все события входа пользователя в домен AD со всех контроллеров домена. На выходе вы получаете таблицу с историей входа пользователя и компьютеров, с которых аутентифицировался пользователь.
# имя пользователя, историю входов которого нужно получить
$checkuser='*ivanov*'
# получаем информацию об истории входов пользователя за последних 2 дня, можете изменить
$startDate = (get-date).AddDays(-2)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
$logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $startDate -ComputerName $dc.HostName
foreach ($event in $logonevents){
if (($event.ReplacementStrings[5] -notlike '*$') -and ($event.ReplacementStrings[5] -like $checkuser)) {
# Remote (Logon Type 10)
if ($event.ReplacementStrings[8] -eq 10){
write-host "Type 10: Remote Logon`tDate: "$event.TimeGenerated "`tStatus: Success`tUser: "$event.ReplacementStrings[5] "`tWorkstation: "$event.ReplacementStrings[11] "`tIP Address: "$event.ReplacementStrings[18] "`tDC Name: " $dc.Name
}
# Network(Logon Type 3)
if ($event.ReplacementStrings[8] -eq 3){
write-host "Type 3: Network Logon`tDate: "$event.TimeGenerated "`tStatus: Success`tUser: "$event.ReplacementStrings[5] "`tWorkstation: "$event.ReplacementStrings[11] "`tIP Address: "$event.ReplacementStrings[18] "`tDC Name: " $dc.Name
}
}
}
}
Получаем информацию об активности пользователя в домене по событиям Kerberos
Также вы можете получить историю аутентификации пользователя в домене по по событию выдачи билета Kerberos (TGT Request — EventID 4768). В этом случае в итоговых данных будет содержаться меньшее количество событий (исключены сетевые входы, обращения к папкам на DC во время получения политик и выполнения логон-скриптов). Следующий PowerShell скрипт выведет информацию о всех входах пользователей за последние 24 часа:
$alluserhistory = @()
$startDate = (get-date).AddDays(-2)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
$logonevents = Get-Eventlog -LogName Security -InstanceID 4768 -after $startDate -ComputerName $dc.HostName
foreach ($event in $logonevents){
if ($event.ReplacementStrings[0] -notlike '*$') {
$userhistory = New-Object PSObject -Property @{
UserName = $event.ReplacementStrings[0]
IPAddress = $event.ReplacementStrings[9]
Date = $event.TimeGenerated
DC = $dc.Name
}
$alluserhistory += $userhistory
}
}
}
$alluserhistory
Обратите, что в этом случае вы не увидите события входов пользователей, которые аутентифицировались с клиентов или приложений, которые используют NTLM вместо Kerberos.
А как через Eventlog понять, что пользователь логинился в систему? Через EventID 4768 я получаю множество лишних записей
Как раз таки 4768 дает не так много событий в журнале DC, в сравнении с 4624.
В теории можно получить с компьютера информацию о локальной входе пользователя по evantid 4624 с Logon Type 2 (это именно событие локального входа, когда пользователь интерактивно ввел пароль с клавиатуры на окне входа в системе).
Также может быть полезен Logon Type 7 — событие разблокировки компьютера.
У меня первый скрипт просто отработал и без ошибок и без результата. Странно
Скрипт для английской версии Windows, в русской возможно будет работать не как ожидается. Нужно тестировать.
Ну и руками посмотрите события с этими кодами в журнале Security, убедитесь что они там появляются в принципе.
Здравствуйте. Настроили аудит и столкнулись с проблемой. События аудита хорошо пишутся на основном контроллере домена, а на резервном весь журнал безопасности в мусорных событиях с кодом 1107. «Служба ведения журнала событий обнаружила ошибку при обработке входящего события от издателя и попытке обработки метаданных для него». Ключевые слова: Аудит успеха совпадают, компьютер различаются. Интервал между записями 2-3 секунды. Однозначно это попытки записи аудита входа-выхода. Что можно сделать на резервном? Настроить фильтр в политике домена и писать только на основной?
Оба DC в одном сайте или разных? Если в одном, то события регистрации могут быть на любом из них. Правильнее будет собирать журналы с обоих
Не понял, что значит «компьютеры различаются». ПОкажите содержимое событий, которые вас смущают
Оба в одном сайте. Случайно обнаружили что на резервном повредился журнал приложений и служб: Microsoft-Windows-GroupPolicy. В его свойствах, путь журнала — Недоступен. Так что он и «спамит» журнал безопасности событиями с кодом 1107. На основном в журнал Microsoft-Windows-GroupPolicy пишутся события. Теперь задача стоит — восстановить этот журнал и запись в него. Не подскажете как это можно сделать?
Всем привет!
Взял за основу данный скрипт и сделал для себя запись в БД по событию 4624 + запись в блокнот
$Outfile = "C:\test\LogOn2.txt"
$server = "server"
$database = "testBD"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$server;Database=$database;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $sql
$SqlCmd.Connection = $SqlConnection
$SqlConnection.Open()
$today = get-date -DisplayHint date -UFormat %Y-%m-%d
Get-WinEvent -FilterHashTable @{LogName="Security";starttime="$today";id=4624} | Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$Type = $event.Event.EventData.Data[0]."#text"
$User = $event.Event.EventData.Data[5]."#text"
$Domain = $event.Event.EventData.Data[6]."#text"
$Computer = $event.Event.System.computer
$strLog = $Computer + " " + $Type + " " + $Time + " " + $User + " " + $Domain
$strLog | out-file $Outfile –append
$sql = "INSERT INTO track_del (ComputerName,TypeAunt,SystemTime,UserName,Domain ) VALUES ('$Computer','$Type','$Time','$User','$Domain')"
}
}
$rowsAffected = $SqlCmd.ExecuteNonQuery();
$SqlConnection.Close()
Проблема в том, что в БД пишет только самое первое событие на текущую дату. Одну строку, как корректно сделать запись все событий ??!
Результат:
$server = "IP"
$database = "NameBD"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$server;Database=$database;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $sql
$SqlCmd.Connection = $SqlConnection
$SqlConnection.Open()
$rowsAffected = 0
$today = get-date -DisplayHint date -UFormat %Y-%m-%y
$date = date
Get-WinEvent -FilterHashTable @{LogName="Security";starttime="$today";id=4624} | where {$_.properties[8].value -eq 7} | Foreach {
$event = [xml]$_.ToXml()
if($event)
{
$Time = Get-Date $_.TimeCreated -UFormat "%Y-%m-%d %H:%M:%S"
$TypeAunt = $event.Event.EventData.Data[0]."#text"
$User = $event.Event.EventData.Data[5]."#text"
$Domain = $event.Event.EventData.Data[6]."#text"
$Computer = $event.Event.System.computer
$sql = "INSERT INTO track_del (ComputerName,TypeAunt,SystemTime,UserName,Domain ) VALUES ('$Computer','$TypeAunt','$Time','$User','$Domain')"
$SqlCmd.CommandText = $sql
$rowsAffected += $SqlCmd.ExecuteNonQuery();
}
}
"I wrote {0} records." -f $rowsAffected
$SqlConnection.Close()
Примерно так будет выглядеть )
Хорошая идея )
А есть какое полноценное ПО с алертами и удобствами унтерфейса для просмотра логов и слежением за несколькими серверами?
Graylog + nxlog
найти бы хороший пример для Graylog + nxlog — который будет описывать сбор данных:
я для эксперимента поставил rsyslog (на postgresql) + сбор логов windows (правда был не nxlog а другая утилита), у меня под 100ГБ в день данных валилось, тут надо грамотно фильтровать данные, которые записывать и ставить ротацию данных в СУБД (это правда скриптами можно самому делать). Ну и главная проблема, из-за большого объема эта задача ресурсоемкая, на тестовом стенде она не пошла, а хорошее железо для тестов не смог найти.
В общем, если будет ссылка с примером то буду очень признателен.
А как сделать так чтобы скрипт показал не одного конкретного пользователя, а всех кто логинелся в определённый промежуток времени
убрать проверку
-and ($event.ReplacementStrings[5] -like $checkuser)
Так это же уберёт проверку конкретного пользователя ли нет? Было бы интересно узнать как указать промежуток времени за который нужно показать данные ?
Поиск по диапазону:
$Begin = Get-Date -Date '1/17/2022 08:00:00'
$End = Get-Date -Date '10/17/2022 17:00:00'
.....
$logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -After $Begin -Before $End -ComputerName $dc.HostName
......
Здравствуйте!
Подскажите пожалуйста, этот скрипт подойдёт чтобы находить все случаи логина пользователей в домене ActiveDirectory c 12:00 до 00:00 часов?
Не последние логоны а именно Все.
В Get-Eventlog можно задать диапазон поиска с помощью параметров [-After ] и [-Before ]
$Begin = Get-Date -Date '1/17/2023 12:00:00'
$End = Get-Date -Date '1/18/2023 00:00:00'
$logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -After $Begin -Before $End -ComputerName $dc.HostName
Почему он ругается на аргумент computername ?
Get-EventLog : Не удается проверить аргумент для параметра «ComputerName». Аргумент пустой или имеет значение NULL. Ука
жите непустой аргумент, не имеющий значение NULL, после чего повторите выполнение команды.
строка:1 знак:105
+ … InstanceID 4624 -After $Begin -Before $End -ComputerName $dc.HostName
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-EventLog], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetEventLogCommand
$domainController = Read-Host «Введите имя доменного контроллера: »
$startDate = (Get-Date).AddDays(-2) # Укажите нужное количество дней
$username = Read-Host «Введите имя пользователя: »
# Подключение к доменному контроллеру с учетной записью администратора
$credential = Get-Credential
$session = New-PSSession -ComputerName $domainController -Credential $credential
# Получение событий logIn и logOut для указанного пользователя из журнала безопасности
$events = Invoke-Command -Session $session -ScriptBlock {
Get-WinEvent -FilterHashtable @{
LogName = ‘Security’
StartTime = $using:startDate
ID = 4624, 4634
} | Where-Object {
$_.Properties[5].Value -eq $using:username -and
$_.Properties[8].Value -in @(2, 10)
}
}
if ($events) {
$output = $events | ForEach-Object {
$timeCreated = $_.TimeCreated.ToString(‘yyyy-MM-dd HH:mm:ss’)
$eventId = $_.Id
$message = $_.Message
$logonType = $message | Select-String -Pattern ‘Logon Type:\s+(\d+)’ | ForEach-Object { $_.Matches.Groups[1].Value }
if ($eventId -eq 4624) {
$eventType = «logIn»
} elseif ($eventId -eq 4634) {
$eventType = «logOut»
} else {
$eventType = «Unknown»
}
[PSCustomObject]@{
Time = $timeCreated
EventType = $eventType
LogonType = $logonType
}
}
$output | Export-Csv -Path ‘C:\Logs\UserEvents.csv’ -NoTypeInformation
Write-Host «Результаты сохранены в файле C:\Logs\UserEvents.csv.»
} else {
Write-Host «Нет доступных событий logIn и logOut для указанного пользователя.»
}
# Завершение сеанса с доменным контроллером
Remove-PSSession -Session $session
# поиск записей Logon на КД для конкретного IP
# имя пользователя, историю входов которого нужно получить
$checkuser=’*gnv*’
# получаем информацию об истории входов пользователя за последних 2 дня, можете изменить
$startDate = (get-date).AddDays(-1)
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs){
$logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $startDate -ComputerName $dc.HostName
foreach ($event in $logonevents){
if (($event.ReplacementStrings[5] -notlike ‘*$’) -and ($event.ReplacementStrings[5] -like $checkuser)) {
# Remote (Logon Type 10)
if ($event.ReplacementStrings[8] -eq 10){
write-host «Type 10: Remote Logon`tDate: «$event.TimeGenerated «`tStatus: Success`tUser: «$event.ReplacementStrings[5] «`tWorkstation: «$event.ReplacementStrings[11] «`tIP Address: «$event.ReplacementStrings[18] «`tDC Name: » $dc.Name
}
# Network(Logon Type 3)
if ($event.ReplacementStrings[8] -eq 3){
write-host «Type 3: Network Logon`tDate: «$event.TimeGenerated «`tStatus: Success`tUser: «$event.ReplacementStrings[5] «`tWorkstation: «$event.ReplacementStrings[11] «`tIP Address: «$event.ReplacementStrings[18] «`tDC Name: » $dc.Name
}
}
}
}
Здравствуйте. В результате скрипта «PowerShell: истории сетевых входов пользователя в домен» получаю ошибку
Get-Eventlog : Не найден сетевой путь.
строка:7 знак:16
+ $logonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $startDate …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-EventLog], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.GetEventLogCommand
Кто может подсказать в чем может быть проблема?
Заранее спасибо
А что делать если в октябре 2023го включаешь в GPO все по инструкции и вообще никаких eventов по логированию нет на сервер AD DC?
Может быть смотрите не на том DC? Проверьте текущий iogonserver на компьютере пользователя.
Если вот такая ошибка, то нужны права администратора? (у меня их нет) или всё таки не включены какие то политики?
Get-Eventlog : Запрошенный доступ к реестру запрещен.
строка:2 знак:16
+ … gonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $B …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-EventLog], SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.GetEventLogCommand
Get-Eventlog : Запрошенный доступ к реестру запрещен.
строка:2 знак:16
+ … gonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $B …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-EventLog], SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.GetEventLogCommand
Get-Eventlog : Запрошенный доступ к реестру запрещен.
строка:2 знак:16
+ … gonevents = Get-Eventlog -LogName Security -InstanceID 4624 -after $B …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-EventLog], SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.GetEventLogCommand
Добрый
Речь не о домене, а об отдельном RDP сервере (да без AD) на базе 2019. До переустановки ОС при каждом логоне (и вход и переподключение к уже созданному сеансу) создавалась событие 4624 с Logon Type = 10.
Переустановили систему и теперь регистрируется 4624 с Logon Type = 7
в локальной политике аудит входа включен (как в статье), сервер на всякий случай перезагрузил.
Мне нужно именно 10 для скрипта обновления пароля.
Кто-нибудь сталкивался с таким?
Logon Type = 7 это разблокировка предыдущего сеанса.
По идее при входе пользователя будет тип 10, а при переподключении к disconnected сесии как раз таки тип 7.
Можно решить правкой скрипта или более жесткими натсройками отключения простаивающих RDP сессий.
Про 7 и 10 я знаю. Но у меня в одной доменной сети при «разблокировке предыдущего сеанса» создается событие 10. Раньше на сервере вне домена также создавалось было событие 10, а вот на новом сервере только 7. В одном из источников было сказано, что событие 7 может возникать при разблокировке несколько раз при одном входе (разблокировке). А у меня триггер на вход для задачи в планировщике.