Приветствую, уважаемый
читатель!
Недавно
читал различные материалы по мониторингу событий безопасности Windows и
наткнулся на интересную статью - https://habrahabr.ru/post/202914/.
Мне понравилась идея, но реализацию я решил слегка переработать. Учитывая, что
пользователи часто являются самым слабым звеном в системе безопасности,
контроль запускаемых на их компьютерах программ
бывает очень полезен. Эту тему и рассмотрим сегодня.
Немного
опишу алгоритм действий.
1) Включаем
аудит нужных нам событий.
2) Из
журнала событий безопасности Windows
за какой-либо период получаем события запуска нового процесса и события
завершения процесса.
3) Упаковываем
нужные поля события в json
и отправляем на Splunk.
4) Проводим
различные операции с полученной информацией.
Включить
аудит событий создания нового процесса и его завершения для рускоязычной версии
Windows
можно следующими командами (спасибо хабр):
auditpol.exe /set/category:"Подробное
отслеживание"/subcategory:"Создание
процесса"/success:enable/failure:enable
auditpol.exe /set /category:"Подробное отслеживание" /subcategory:"Завершение процесса" /success:enable /failure:enable
Для
получения событий будем использовать powershell и его командлет Get-EventLog. Текст скрипта и пояснение
некоторых моментов ниже.
$host_name =
$env:COMPUTERNAME
$events =
Get-EventLog -LogName
Security -instanceID
4688,4689 -Newest 1000 | select EventID,MachineName,Message,TimeGenerated
$events |
foreach {
"`n
New Event*********************************************** `n"
$EventID
= $_.EventID
if
($EventID -eq
4688) {
$message
= $_.Message.split("`n").replace("`t","")
$time
= $_.TimeGenerated.toString()
$intNum
= ($message
| Select-String
-pattern "ИД нового процесса").ToString().Replace("ИД нового процесса:","").Replace("`r","")
| ConvertTo-Json
$ProcName
= ($message
| Select-String
-pattern "Имя нового процесса").ToString().Replace("Имя нового процесса:","").Replace("`r","")
| ConvertTo-Json
$JSONDoc
= @"
{
"host": "http_host",
"index": "main",
"sourcetype": "ProcStart",
"event": {
"EventID": "$EventID",
"GenTime":
"$time",
"Hostname": "$host_name",
"ProcID": $intNum,
"ProcName":
$ProcName
}
}
"@
$JSONDoc
Invoke-WebRequest
-uri "http://<splunkip>:8088/services/collector"
-Headers @{"Authorization"="Splunk
D3E1D511-0BFC-4ACF-AEE1-B7879E581BA2"} -Method
POST -Body
$JSONDoc
}
if
($EventID -eq
4689) {
$Endmessage
= $_.Message.split("`n").replace("`t","")
$time
= $_.TimeGenerated.toString()
$intNum
= ($Endmessage
| Select-String
-pattern "Идентификатор процесса:").ToString().Replace("Идентификатор процесса:","").Replace("`r","")
| ConvertTo-Json
$ProcName
= ($Endmessage
| Select-String
-pattern "Имя процесса:").ToString().Replace("Имя процесса:","").Replace("`r","")
| ConvertTo-Json
$JSONDoc
= @"
{
"host": "http_host",
"index": "main",
"sourcetype": "ProcEnd",
"event": {
"EventID": "$EventID",
"GenTime": "$time",
"Hostname": "$host_name",
"ProcID": $intNum,
"ProcName": $ProcName
}
}
"@
$JSONDoc
Invoke-WebRequest
-uri "http://<splunkip>:8088/services/collector"
-Headers @{"Authorization"="Splunk
D3E1D511-0BFC-4ACF-AEE1-B7879E581BA2"} -Method
POST -Body
$JSONDoc
}
}
Пояснение:
1) Получаем
события запуска нового процесса(4688) и завершения процесса(4689) из журнала
безопасности. Для примера берем 1000 новых событий.
Get-EventLog -LogName Security -instanceID
4688,4689 -Newest
1000
2) Для
удобства избавляемся от ненужных специальных символов в тексте события.
$message = $_.Message.split("`n").replace("`t","")
3) Из
текста события получаем нужные строки и переводим их в json-формат.
$intNum =
($message |
Select-String -pattern
"ИД нового процесса").ToString().Replace("ИД нового процесса:","").Replace("`r","")
| ConvertTo-Json
$ProcName =
($message |
Select-String -pattern
"Имя нового процесса").ToString().Replace("Имя нового процесса:","").Replace("`r","")
| ConvertTo-Json
4) Отправляем
POST-запрос
с событием на Splunk-сервер.
В качестве Authorization-заголовка добавляем токен.
Invoke-WebRequest -uri "http://<splunkip>:8088/services/collector"
-Headers @{"Authorization"="Splunk
D3E1D511-0BFC-4ACF-AEE1-B7879E581BA2"} -Method
POST -Body
$JSONDoc
Все
события, отправляемые на Splunk-сервер,
разделены на 2 sourcetype. В один складываются события запуска процесса (ProcStart),
а в другой события завершения процесса (ProcEnd). Сделано это для того, чтобы
взаимосвязь событий между собой реализовать средствами Splunk, а не powershell, т.к. Splunk изначально
для этого и придуман.
Теперь
переходим к Splunk.
Для начала выведем список всех процессов, запущенных на компьютере, с указанием
времени выполнения. Вбиваем следующий запрос:
sourcetype=ProcEnd
| eval EndTime = GenTime
| join type=inner ProcID [search sourcetype=ProcStart
| eval StartTime = GenTime
| table ProcID,StartTime]
| eval St = round(strptime(EndTime,"%d.%m.%Y
%H:%M:%S")-strptime(StartTime,"%d.%m.%Y %H:%M:%S"),0)
| eval Duration = strftime(St,"%M:%S")
| table ProcID,StartTime,EndTime,Duration,ProcName
Результат
запроса ниже:
Данный
запрос соединяет между собой события из 2-х sourcetype по
ключевому полю ProcID,
в котором хранится значение идентификатора запущенного или завершённого
процесса. Дополнительно вычисляется время выполнения конкретного процесса и
указывается в отдельном поле «Duration».
Наиболее
интересным является следующая часть запроса:
| eval St = round(strptime(EndTime,"%d.%m.%Y
%H:%M:%S")-strptime(StartTime,"%d.%m.%Y %H:%M:%S"),0)
| eval Duration = strftime(St,"%M:%S")
Оператор
strptime
позволяет перевести время из текущего формата в unix epoch time (UET), а оператор strftime позволяет выполнить
обратную манипуляцию. Перевод времени в UET позволяет выполнять математические
операции.
Теперь
построим круговую диаграмму для 7 наиболее активно используемых программ.
Запрос и результат ниже.
sourcetype=ProcEnd
| eval EndTime = GenTime
| join type=inner ProcID [search sourcetype=ProcStart
| eval StartTime = GenTime
| table ProcID,StartTime]
| eval St = round(strptime(EndTime,"%d.%m.%Y
%H:%M:%S")-strptime(StartTime,"%d.%m.%Y %H:%M:%S"),0)
| stats sum(St) as AllTime by ProcName
| sort -AllTime
| head 7
Немного
усложним задачу. Предположим, мы заведомо не хотим знать об активности той или
иной программы на компьютере пользователя, например, активность системного
процесса. Для этого создадим в директории “/opt/splunk/var/run/splunk/csv” файл
Process.csv, например, следующего содержания:
Proc
"C:\Windows\System32\wbem\WmiPrvSE.exe"
"C:\Windows\System32\SearchProtocolHost.exe"
Теперь
необходимо добавить в запрос соответствующее условие, которое будет отбрасывать
события:
sourcetype=ProcEnd
| eval EndTime = GenTime
| join type=inner ProcID [search sourcetype=ProcStart
| eval StartTime = GenTime
| table ProcID,StartTime]
| eval St = round(strptime(EndTime,"%d.%m.%Y
%H:%M:%S")-strptime(StartTime,"%d.%m.%Y %H:%M:%S"),0)
| search NOT [| inputcsv Process | table ProcName]
| stats sum(St) as AllTime by ProcName
|
sort -AllTime
|
head 7
Как
видим ситуация изменилась J
Собственно
вот такой механизм контроля активности ПО.
Комментариев нет:
Отправить комментарий