Аудит Active Directory средствами Powershell с оповещением об изменениях.

Цель нашей компании - предложение широкого ассортимента услуг на постоянно высоком качестве обслуживания.

Задать вопрос
Наши специалисты ответят на любой интересующий вопрос по услуге
Начну серию публикаций по мониторингу Active Directory.
В данных статьях я приведу самые основные проблемы и пути их решения. На основе этих данных функционал легко расширяется до тех требований, которые Вам необходимы.
Учитывая, что сейчас для всех ОС, начиная с Windows Server 2003 R2 и Windows XP SP3 доступен Powershell. Думаю, что данная статья окажется полезным подспорьем, т.к. не требует от администратора введения никаких дополнительных средств, т.е. по сути – мониторинг штатными средствами.



Итак начнем.

Мониторинг Active Directory



На всех блог-комьюнити посвященных IT можно встретить множество статей по мониторингу AD, но… но больше 90% из них посвящены использованию сторонних приложений, в большинстве своем стоящих определенную сумму денег, которую не каждое предприятие готово отдать, пусть даже не большую. Наверное рекордсмен по количеству статей – это продукт от компании NetWrix Corporation. Тут и там IT-специалисты расписывают замечательные возможности данной программы. Да чего греха таить, и сам пользовался данной программой в демо-режиме. Честно скажу – понравилась, все просто и доступно, но денег на нее не дают, а значит к концу демо-периода AD снова останется без “зоркого” глаза. Что меня в корне не устраивало.

Немного тоерии


Как известно в политиках безопасности в ОС Windows всех мастей есть возможность вести аудит событий. Данный аудит позволяет автоматически генерировать записи в Event Log в журнале “Безопасность”. Аудит можно вести за несколькими типами событий, например: вход в систему, доступа к объектам, управлениями учетными записями, изменения политик и прочее. Всего 9 типов событий. Это базовый аудит. Начиная с Windows 7 и Windows Server 2008R2 количество событий аудита возросло до 53. С помощью которых можно более детально вести аудит только нужных событий. Более подробную информацию по расширенным политикам аудита можно прочитать тут.
Но как известно тем, кто хоть раз заглядывал в EventLog в раздел безопасности – найти там что либо – если и не невозможно, то по крайней мере очень сложно.

Идея...

И тут родилась идея… раз Windows умеет создавать запись в EventLog о произошедшем событии, значит теоретически данную информацию можно получить. Одно “но”… уж больно большой этот лог, чтобы в нем искать нужное событие вручную, да и со временем если не ограничить размер лога, он может разрастись в десятки гигабайт, что само по себе уже не хорошо. Значит необходимо решить проблему по поиску нужной информации в EventLog’е автоматически. Благо, что каждый тип события (например создание учетной записи пользователя) имеет свой ID, по которому его можно найти.
Значит для решения задачи поиска нам нужно всего лишь отыскать данное событие в журнале.
Для Powershell 2.0 есть специальный командлет для работы с EventLog’ом – Get-WinEvent.
Используя данный командлет можно получить определенную запись в EventLog’е.

Реализация

Допустим мы указали в групповых политиках, которые применяются на контролеры домена, вести аудит событий связанных с учетными записями.
Тогда любое действие с учетной записью, заведенной в AD, будет генерировать событие, которое будет будет создавать запись в EventLog с определенным идентификатором. Например при добавлении в домен компьютера на контролере домена, где производилась эта операция, в EventLog’е в журнале “Безопасность” появится запись с идентификатором ID=4741, в которой будет указано в какое время, кто и какой компьютер добавил в домен.
Для получения последнего события с данных идентификатором воспользуемся запросом Powershell:

Get-WinEvent -FilterHashtable @{LogName=”Security”;ID=4741}

Но формат вывода к сожалению желает оставлять лучшего, т.к. очень много лишней информации, такой как идентификаторы безопасности, куча атрибутов.

TimeCreated  : 12.07.2012 14:02:19
ProviderName : Microsoft-Windows-Security-Auditing
Id           : 4741
Message      : Создана учетная запись компьютера.

               Субъект:
                   Идентификатор безопасности:        S-1-5-21-451469775-2953165952-2320738315-500
                   Имя учетной записи:        administrator
                   Домен учетной записи:        DOMAIN
                   Идентификатор входа:        0xb3acf

               Новая учетная запись компьютера:
                   Идентификатор безопасности:        S-1-5-21-451469775-2953165952-2320738315-2979
                   Имя учетной записи:        TEST$
                   Домен учетной записи:        DOMAIN

               Атрибуты:
                   Имя учетной записи SAM:    TEST$
                   Отображаемое имя:        -
                   Основное имя пользователя:    -
                   Домашний каталог:        -
                   Домашний диск:        -
                   Путь к сценарию:        -
                   Путь к профилю:        -
                   Рабочие станции пользователя:    -
                   Последний пароль задан:    <никогда>
                   Срок действия учетной записи истекает:        <никогда>
                   Идентификатор основной группы:    515
                   Разрешено делегировать:    -
                   Старое значение UAC:        0x0
                   Новое значение UAC:        0x85
                   Управление учетной записью пользователя:
                       Учетная запись отключена
                       "Пароль не требуется" - включено
                       "Учетная запись доверия рабочей станции" - включено
                   Параметры пользователя:    -
                   Журнал SID:        -
                   Часы входа:        <значение не задано>
                   DNS-имя узла:        -
                   Основные имена служб:    -

               Дополнительные сведения:
                   Privileges        -


Нас же интересует самая основная информация: Время, кто создал, имя компьютера. Для этого “немного” подправим наш запрос:
Get-WinEvent -FilterHashtable @{LogName=”Security”;ID=4741} | Select TimeCreated,@{n=”Оператор”;e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “SubjectUserName”} |%{$_.’#text’}}},@{n=”Имя компьютера”;e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “SamAccountName”}| %{$_.’#text’}}}

В итоге результатом данного запроса станет уже удобная для глаза информация:

TimeCreated : 12.07.2012 14:02:19
 Оператор : administrator
 Имя компьютера : TEST$

Данный запрос рассматривает событие в EventLog’у как XML объект. И выбирает нужные нам значения, т.е. время (TimeCreated), Оператора и Имя компьютера.

Как видите код не совсем удобочитаем. Для возможности работы с событиями в Windows Eventlog предусмотрен специальный класс .Net, который может разбирать каждое событие на подстроки, а так как Powershell, по сути — тот .NET, то и в нем доступны данные возможности.

Вот к примеру данный код разбирает событие по подстрокам:

Get-Eventlog Security -InstanceId 4768|
   Select TimeGenerated,ReplacementStrings |
   % {
     New-Object PSObject -Property @{
     UserName = $_.ReplacementStrings[0]
     IPAddress = $_.ReplacementStrings[9]
     Date = $_.TimeGenerated
    }
   }


В итоге получим что-то вроде такого:

 Date : 12.07.2012 14:02:19
 Username : administrator
 IPAddress : 10.10.10.1


Данный код намного проще читать.

Рассмотрим поподробнее запросы.


1 вариант (запрос рассматривает событие как XLM):

Если открыть любою запись в EventLog’е, то Вы увидите 2 закладки: Общие и подробности.
Если перейти на вкладку “подробности” и выбрать режим просмотра: “Режим XML”, то увидим как раз таки структуру события в виде XML.
Распарсив данное событие как XML и выбрав оттуда необходимые нам значения: В разделе Event.EventData.Data в параметре под именем SubjectUserName скрывается имя пользователя который создал компьютер, а в параметре под именем SamAccountName – имя созданного компьютера.

2 вариант (разбор под подстрокам):

Тем же самым образом открываем событие как XML, находим раздел Event.EventData.Data, и считаем строки (начиная с 0) — это и есть индексы наших подстрок. Находим строку с нужным нам значением, и считаем какая она по счету.

Теперь нужно куда то вывести эту информацию, не хранить же ее в консоли.
А еще лучше если она будет отправляться администратору, скажем, на почту.
В Powershell 2.0 есть возможность консольно устанавливать SMTP сессии и отправлять письма.
Send-MailMessage– командлет который выполняет данную функцию.
Для отправки сообщения нем необходимо указать SMTP-сервер, адрес отправителя, адрес получателя, тело письма, тему письма, имя пользователя и пароль.
В итоге получим следующий запрос, который будет искать последнее событие под идентификатором ID=4741 и отправлять на почту администратору информацию.


#Определяем все переменные для отправки
 $Theme = “Добавлен новый компьютер в домен” # Первая строчка в теле письма, чтобы понимать о чем речь.
 $Subject = “Создание компьютера” # Тема сообщения

$Server = “mail.domain.ru” # SMTP Сервер
 $From = “audit@domain.ru” # Адрес отправителя
 $To = “admin@domain.ru” # Получатель
 $pass = ConvertTo-SecureString “PASSWORD” -AsPlainText -Force #Пароль от учетной записи
 $cred = New-Object System.Management.Automation.PSCredential(“AUDIT” , $pass) #Имя пользователя и пароль
 $encoding = [System.Text.Encoding]::UTF8 #Устанавливаем кодировку UTF8 для корректного отображения информации в теле письма

#Собственно сам запрос поиска события. Выбирается последнее произошедшее событие с таким ID. Данные записываются в переменную Body.

$Body=Get-WinEvent -FilterHashtable @{LogName=”Security”;ID=4741} | Select TimeCreated,@{n=”Оператор”;e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “SubjectUserName”} |%{$_.’#text’}}},@{n=”Имя компьютера”;e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq “SamAccountName”}| %{$_.’#text’}}} | select-object -first 1

#Отправка письма.
 Send-MailMessage -From $From -To $To -SmtpServer $server -Body “$Theme `n$BodyM” -Subject $Subject -Credential $cred -Encoding $encoding


Итог


Сохраняем данный скрипт в файл с расширением ps1, например сюда: D:\Scripts\ADCompAdd.ps1
Открываем консоль Powershell.
Набираем команду: Set-ExecutionPolicy Unrestricted

Жмем “Y” и Enter. Тем самым мы разрешаем выполнение Powershell-скриптов на сервере.
Перетаскиваем скрипт в консоль (Drag and Drop) и жмем Enter. Проверяем, что скрипт выполнился без ошибок (т.е. в консоли никаких надписей красного цвета не появилось). Проверяем почту на наличие нового сообщения, которое содержит в себе необходимые нам данные.

Осталось только как то заставить запускаться данный скрипт в момент когда событие произошло.
Тут нам на помощь придет “Планировщик заданий”.
В планировщике есть возможность реакции на определенное событие в EventLog.
Создаем задание, где в тригере указываем реагировать на событие под номером 4741 которые появляется в журнале Security.
Так же указываем что необходимо запустить данный скрипт. Для этого указываем в “действиях”, что хотим запустить программу, в поле “Программа или сценарий” пишем “powershell”. В поле “Добавить аргументы (необязательно)” пишем ” -nologo -noprofile -File “D:\Scripts\ADCompAdd.ps1″ ”

Теперь тестируем как работает созданная структура. Создаем тестовый компьютер в любом подразделении в AD. И проверяем почту на наличие сообщения.

Скрипт не совсем безопасен т.к. содержит в себе имя пользователя и пароль в открытом виде, поэтому настоятельно рекомендую, если решите воспользоваться данным скриптом, то используйте учетные записи для отправки сообщений с минимальным набором прав.

По моим замерам время реакции на событие 1 секунда. Т.е. со времени создания до получения письма проходит 1 секунда. Конечно при условии, что вы используете свой локальный почтовый сервер, а не где нибудь в Интернете. Там задержка может быть больше. Но в целом тоже не высокая.

В итоге взяв за основу данный скрипт и изменив в нем номер события и данные которые необходимо доставать из события, можно осуществлять мониторинг за всеми операциями с учетными записями в AD: создание-удаление, отключение-включение, блокировки-разблокировки., добавления в группы и исключения и прочее. В общем любой мониторинг событий, который позволяет вести аудит Windows. Просто необходимо изменить фильтр XML в запросе, для этого посмотреть необходимое событие в XML-режиме, выбрать необходимые значения и вписать их в фильтр запроса.

PS:


Вот некоторые полезные идентификаторы событий для Windows Server 2008R2:

ID=4741 Создание компьютера в домене

ID=4743 Удаление компьютера из домена

ID=4728 Добавление в группу безопасности

ID=4729 Удаление из группы безопасности

ID=4720 Создание пользователя

ID=4726 Удаление пользователя

ID=4740 Блокировка учетной записи

ID=4767 Разблокировка учетной записи

ID= 4722 Включение учетной записи

ID=4725 Отключение учетной записи

Мгновенное оповещение.


Чем хороши мгновенные оповещения, так это тем, что нет необходимости постоянно проверять почту на предмет новых сообщений — сообщения приходят сами и дают о себе знать сразу же (В зависимости от настроек клиента, конечно же).
Лично для себя я сделал, чтобы сообщения открывались поверх всех окон. Конечно, чтобы не заспамит самого себя, такие оповещения отправляются на критически важные события.
К критически важным я отнес: неудачные попытки входа на контролеры домена, неудачные попытки входа на сервис VPN (PPTP на WIndows). Так же добавил эту функцию в скрипты мониторинга за AD. Т.к. у меня доступ к AD имеют несколько человек, то со временем можно потерять нить актуальных данных (что-то, когда-то, кого-то удалил/переместил/добавил а ты и не в курсе). И данные сообщения будут как раз кстати, чтобы в реальном времени знать об изменениях.

Поиски решения

Когда мне пришла идея о таком роде оповещения (учитывая тот факт, что у нас в организации достаточно активно используется Jabber-сервис) первое что я сделал, это забил к гугл Powershell Jabber. Первой же ссылкой меня отправило на сайт не безызвестного на просторах форумов Microsoft Technet Xaerg'а. То что я там увидел меня не могло не порадовать: «А знаете ли вы, что оснастка NetCmdlets, включающая командлеты для работы с огромным количеством сетевых протоколов, доступна совершенно бесплатно для некоммерческого использования?»
И приводится список доступных команд. «Это то что мне нужно, да еще и бесплатно!!!» — подумал я и огорчился когда прошел на сайт разработчика этой оснастки командлетов, оказывается у них нет бесплатной версии, есть только триальная на 1 месяц, после чего нужно вновь запрашивать ключ. Только после этого я обратил внимание на дату статьи, она оказалась 2008 года – старовата :(.
Ради эксперимента скачал триальную версию. Установил на сервер, на котором хочу использовать оповещения. Установка прошла на УРА. Сразу же стали доступны новые коммандлеты. Синтаксис у них довольно простой и с отправкой сообщений проблем не возникло. Какое-то время я так и использовал эту триальную лицензию, раз в месяц ее перерегистрировав. Но само ощущение, что используешь триальную версию меня угнетало, еще больше угнетал тот факт, что необходимо ее каждый месяц регистрировать для каждого сервера, где она установлена. А так как в инфраструктуре на тот момент присутствовало чуть менее 30 серверов, даже мысль о перегистрации хоть раз в месяц на всех серверах приводила меня в ужас.
Когда со временем стало посвободнее, я решил добить эту идею. Необходимо было средство, позволяющее посредством Powershell, отправлять сообщения, используя протокол XMPP. При этом важным фактором должно быть условия использования данного средства — оно должно быть бесплатным.

Я снова начал мучать гугл. И мои усилия не пропали даром. В один прекрасный клик я попал на страничку с утилитой, которая как раз таки позволяет отправлять сообщения из PS-консоли, используя XMPP-протокол.
Особенно меня порадовала надпись, красующаяся в заголовке страницы: Project Hosting for Open Source Software. Что наталкивало меня на мысль, что данный продукт бесплатен в использовании — как раз то, что мне нужно.

Аудит неудачных попыток входа на сервер, с оповещением по электронной почте, Jabber-сервису, и записью в лог-файл.


#Поиск последней записи в WIndowsEventLog на предмет неудачной попытки входа на сервер, и запись значения в переменную Body
$HostName = HostName
$Body=Get-WinEvent -FilterHashtable @{LogName="Security";ID=4625} | Select TimeCreated,@{n="User";e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq "TargetUserName"} | %{$_.'#text'}}},@{n="ComputerName";e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq "WorkstationName"}| %{$_.'#text'}}},@{n="IPAddress";e={([xml]$_.ToXml()).Event.EventData.Data | ? {$_.Name -eq "IPAddress"}| %{$_.'#text'}}} | select-object -first 1

#$BodyL - переменная для записи в текстовый лог-файл
$BodyL = "`n"+$Body.TimeCreated +"`t"+ $Body.User +"`t"+ $Body.ComputerName +"`t"+ $Body.IPAddress
#$Body - переменная для тела письма при отправке сообщения на почту и Jabber
$Body = "`nВремя: "+$Body.TimeCreated +"`nИмя пользователя: "+ $Body.User +"`nКомпьютер-источник: "+ $Body.ComputerName +"`nIP источника: "+ $Body.IPAddress

#$Theme - тема письма. $Hostname - имя сервера
$Theme = "Неудачный вход в систему на "+$hostname

#Отправка Jabber-сообщения

Add-PSSnapin poshxmpp
new-client -JabberId AUDIT@domain.ru -Password PASSWORD
Send-Message admin@domain.ru "$Theme      $Body"
$PoshXmppClient.Close()



#Описание переменных для отправки e-mail сообщения о инциденте
$Subject = "Неудачный вход в систему на "+$hostname

$Server = "mail.domain.ru" # SMTP Сервер
$From = "audit@domain.ru" # Адрес отправителя
$To = "admin@domain.ru" # Получатель
$pass = ConvertTo-SecureString "PASSWORD" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential("AUDIT" , $pass)
$encoding = [System.Text.Encoding]::UTF8
#Отправка e-mail
Send-MailMessage -From $From -To $To -SmtpServer $server -Body "$Theme `n$Body" -Subject $Subject -Credential $cred -Encoding $encoding
#Запись данных в текстовый лог-файл FaildConnect.txt
$BodyL | out-file "\ServerNameServerLogFilesServerFaildConnect.txt" -append


Как я писал в первой части, чтобы скрипт автоматически отрабатывал необходимо поместить его в планировщик задач и настроить запуск данного скрипта при обнаружении в EvenLog события с ID = 4625в журнале Security.

Рекомендации.


Именно подобные скрипты у меня работают на VPN-сервере и на всех контролерах домена.
Теперь я всегда знаю, когда и кто подключается к VPN, например. Или когда кто-то пытается подобрать пароль на доступ к серверу.
Так же рекомендую навесить такой скрипт на те сервисы, которые «светятся» в Интернет, к примеру службы терминального доступа.
А запись в отдельный файл, позволит Вам, в будущем, проанализировать подключения. Лог, кстати говоря, можно открыть через табличный редактор (MS Excel или OO Calc) и уже работать с логом как с таблицей (сортировать, фильтровать и т.д.).

Источник
Заказать услугу
Оформите заявку на сайте, мы свяжемся с вами в ближайшее время и ответим на все интересующие вопросы.