46,6
Рейтинг
Varonis Systems
Защита от внутренних угроз и комплексных кибератак
15 июля

Руководство по анализу Sysmon-угроз, часть 3. Углубленный анализ Sysmon-угроз с помощью графов

Блог компании Varonis SystemsИнформационная безопасностьСистемное администрированиеPowerShellBig Data
Перевод
Автор оригинала: Andy Green


Эта статья является третьей, и финальной, частью серии по анализу Sysmon-угроз. Все остальные части серии:

Часть 1. Знакомство с анализом логов Sysmon
Часть 2. Использование данных из Sysmon событий для выявления угроз
Часть 3. Углубленный анализ Sysmon-угроз с помощью графов (мы тут)

Поиск нестандартных подграфов с данными событий Sysmon (простой пример)


Прежде чем мы ознакомимся с примером выявления аномалий в подграфах, указывающих на потенциальную угрозу (и если эти слова не пробуждают в вас ботаника, то ничто уже не пробудит!), давайте сделаем небольшое отступление.

В этом месте я обязан сделать предупреждение: данный пост вместе с кодом на GitHub не может заменить решение корпоративного класса. Оно может помочь выявить угрозы в меньшем масштабе, но моя благородная задача состоит в том, чтобы помочь представителям IT-безопасности понять и по достоинству оценить реальные решения по защите от угроз. И один из способов достичь этого – самостоятельно создать собственное решение (с моей помощью).

Домашние эксперименты помогут понять, насколько сложно масштабировать DIY-софт по выявлению угроз. Вам придётся работать с наборами big data и со всем, что с ними связано: чисткой (что крайне непростая задача), эффективной обработкой (найти нужные структуры данных, алгоритмы и т.д.) и предоставлением результатов с низким количеством ложных cрабатываний, чтобы ваши же коллеги потом не полезли на вас с кулаками. С учётом этого вы можете рассмотреть уже готовое решение по обнаружению угроз… но только после завершения нашей серии статей и проведения собственных экспериментов.

Выставление весовых коэффициентов графа


Один из простых способов построить решение по защите от угроз, которое не полагается на сигнатуры вредоносного софта, — это использовать граф угроз из предыдущей части.

Такой граф соединяет вершины процессов на базе записей из журнала событий Sysmon.
Обратите внимание: я не выделял каждое событие запуска процесса (Event ID 1 в событиях Sysmon) в отдельную вершину. Вместо этого я создал более абстрактный граф, который показывает, скажем, что вершина PowerShell имеет одну связь с любым приложением, которое она запустила из-под любого пользователя – одну связь для Excel, одну для браузера и т.д.

Вид дерева PSQuickGraph моего графа угроз Sysmon. Обратите внимание на аномальную ветку под cmd.exe


Вид дерева PSQuickGraph моего графа угроз Sysmon. Обратите внимание на аномальную ветку под cmd.exe


Однако нам всё же желательно отслеживать частоту запускаемых процессов. Например, если PowerShell запустил «whoami» 1 раз и 10 раз устаревший Windows-редактор «Notepad.exe», то данные ребра графа, отходящие от вершины PowerShell, должны быть отмечены соответствующими «весами» в 1 и 10 соответственно. Логично?

Во многих простейших алгоритмах детектирования угроз данный вес становится метрикой сравнения регионов графа. Основная мысль заключается в том, что подграф с более низким средним уровнем веса по сравнению со средним весом в целом, является подозрительным.
Не так ли? Редко посещаемая вершина является аномальной зоной. Поэтому если пользовательские действия при анализе потенциальных угроз уходят в сторону редко используемого подграфа, следует поднять уровень тревоги до жёлтого.

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

Говорил ли я уже, что алгоритмы Дага Финке в PowerShell для структур данных являются великолепным и мощным инструментом? Без его работы я бы ничего не достиг в своём проекте графа аномалий. Повторное тебе спасибо, Даг!

С помощью его PowerShell-библиотеки прекрасных граф-функций я легко могу посчитать вес моего Sysmon-графа угроз посредством всего нескольких строчек PS, а также узнать средний вес вершины для всего графа. По мере прохождения графа, код также назначает каждой вершине вес всех её исходящих рёбер:

$AW=0 #average weight
$GW=0 #total weight

$mset = [System.Collections.ArrayList]@() #master set of subraphs
#calculate total weight by summing up the frequencies or weights of the edges
foreach ($e in $g.getAllEdges() ) {
    $GW = $GW + $e.weight
}
write-host "Weight of Graph: " $GW
$AW = $GW / $g.vertices.count
write-host "Average weight per vertex: " $AW

#assign weight of edges to vertice
for ($i=0; $i -lt $g.vertices.count; $i++) { 
   $w=0
   $v=$g.vertices[$i]
   foreach($e in $v.getEdges()) {
      if($e -eq $null) {continue}
      $w=$w + $e.weight
   }
   $v.value.Weight = $w
}

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

Самая сложная часть моего PowerShell скрипта графа аномалий — который я скоро покажу — это найти регионы графа, которые реже всего встречаются, а затем найти наибольший подграф, содержащий их. Возможно, что для выполнения этой задачи вам потребуется пролистать какую-нибудь старую книгу по информатике. Но на самом деле это не так сложно написать!

Я использовал классический поиск в ширину для моего графа через посещение каждой вершины, а затем расширял его за счёт соседних вершин до тех пор, пока мой подграф не достигнет определённого порога в зависимости от среднего веса вершины. Вот так:

function extend-subgraph($v, $t) {
    $vertexQueue = New-Object Queue
    
    #initialize
    $vertexQueue.enqueue($v)
    $h=$v.value.Weight
    $s=@() #subgraph
    $s+=$v
    $extend=$false
    while (!$vertexQueue.isEmpty()) { #bfs
        $currentVertex = $vertexQueue.dequeue()
        $es= $currentVertex.getEdges()
        foreach($e in $es) {
            $ev= $e.endVertex                
            if ((($h + $ev.value.Weight)/($s.count+1) -lt $th)  {        
                #extend the sub-graph
                $s+=$ev
                $h =$h + $ev.value.weight
                #queue it up
                $vertexQueue.enqueue($ev)
            }
        }

Небольшая ремарка для любителей DIY: для создания массива массивов используйте тип arraylist и вы убережёте себя от большой головной боли.

Угрозы и подграфы с низким весом


Существует много разных алгоритмов аномальных графов. Тот, который я использовал, основывается на некоем graphBAD, который я нашёл на просторах интернетов, — и я дам ссылку, как только найду его снова.

В целом, главной проблемой в практическом детектировании угроз является поиск хорошего набора данных для формирования базового уровня. Будучи фултайм-блоггером и парттайм специалистом по выявлению угроз, мне так и не удалось создать достаточно интересный Sysmon-лог, содержащий множество разных приложений. Было достаточно сложно сгенерировать аномальные подграфы, так как у меня не было достаточно большого разброса по весам. Так или иначе, при использовании реального сервера у вас может оказаться в руках куда лучший набор данных, чем эпизодическое использование AWS инстанса Windows, как в моём случае.

Написанный мной PS-скрипт аномальных графов вполне выдавал подозрительные подграфы с низкими средними весами. И мне удалось даже поймать несколько интересных окружений (см. ниже).

Алгоритм весов подграфов в действии: интересное окружение с низким весом подграфа №7


Алгоритм весов подграфов в действии: интересное окружение с низким весом подграфа №7


Как я упоминал ранее, существуют и другие алгоритмы обнаружения аномалий в графах с метриками, отличными от простых весовых коэффициентов, стоящие своего времени на изучение. Один из них ищет кластеры «схожих» вершин и подмечает соединения или связи между разными окружениями. В этом случае аномалия заключается в пользователе или процессе, который связывает окружения с помощью каких-то других характеристик. Логично, не так ли?

Если внутренний ботаник в вас силён, можете ознакомиться со SCAN (Structural Clustering Algorithm for Networks), который как раз осуществляет вышеописанное. Вместе с PowerShell алгоритмами Дага Финке вы даже можете его применить. Я сам хочу взяться за этот проект и выложить его скоро в свой GitHub.

Поиск аномалий посредством случайных обходов


Давайте закончим данный раздел ещё одним способом находить аномалии в графе угроз. Я ссылался на этот подход в конце предыдущей части . Для меня, как для человека с математикой на «ты», он является более интуитивным. А фанаты старого ТВ-шоу numb3rs сразу же узнают концепцию [прочищает горло] цепей Маркова.

Для всех оставшихся – вы можете рассматривать это как «случайный обход» по графу. На каждой из вершин мы кидаем кубик и выбираем ребро графа в зависимости от его веса: чем больше вес ребра, тем выше шанс, что мы пойдём по нему. Вам необходимо разбить граф на две части – он называется двудольным графом в теории графов – с пользователями в одной части и приложениями в другой.

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

Плюс в карму тому, кто связал это с PageRank алгоритмом Google. Я опишу данный момент подробнее в следующей секции, но заинтересованные могут погуглить фразу random walk with restart.

Теория случайного обхода и EQL-практика


Давайте сделаем ещё одно отступление и проанализируем, чего мы пытаемся достичь с помощью лога Sysmon, являющимся великолепным инструментом детектирования угроз и проведения расследований после инцидентов.

  • В предыдущих частях нашей серии я показал, как обрабатывать и вывести базовую информацию о процессах из данных Sysmon. Но в Sysmon логе сокрыто ещё больше информации, если мы будем рассматривать взаимодействие родительского и дочернего процесса как звено графа.
  • В части 2 нашей серии мы преобразовали лог Sysmon в граф, получив тем самым куда больше контекста, что позволило нам продвинуться за пределы простого поиска конкретных вредоносных сигнатур.
  • В третьей части мы углубились в обзор одного простого алгоритма, рассматривающего связи рёбер как весовые коэффициенты. Секции графа, весящие меньше (в терминах рёбер), чем общий средний вес по всему графу, могут являться потенциальной угрозой. Я собираюсь выложить PowerShell скрипты алгоритмов из данной секции в моём GitHub (после наведения в них лоска).

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

Случайный обход графа уязвимостей из данных на базе событий Sysmon


Вместо анализа структуры самого графа, мы можем рассматривать связи как некий путь или дорожную карту, в котором каждое приложение является отдельной остановкой по пути следования. Из данных журнала Sysmon мы можем получить частоту , с которой каждое приложение запускается от своего родителя.

Если вы посмотрите мой скрипт графа угроз на GitHub, то обнаружите, что эта частота сохраняется внутри каждого объекта-ребра с помощью чудесных PowerShell-алгоритмов Дага Финке.

Можно рассматривать частоту пересечения каждого из рёбер графа уязвимостей как вероятность!


Можно рассматривать частоту пересечения каждого из рёбер графа уязвимостей как вероятность!


Следующим шагом напрашивается использования этой информации для нахождения вероятности, скажем, запуска PowerShell-ом приложения taskmgr.exe, анализатора процессов Windows, блокнота или hostname.exe.

К чему я клоню?

Вкратце: я могу создать вероятностную матрицу переходов, так любимую последователями Маркова и частно используемую в системах моделирования. Фактически, бросание кубика, переход к следующему приложению в графе и повтор сих действий является случайным обходом графа. В конечном счёте, данный математический метод ранжирует каждую вершину графа в соответствии с вероятностью попадания туда из стартовой точки. И вы узнаете, что, скажем, запуск электронных таблиц из проводника Windows является крайне обыденным процессом, а движка сценариев Windows Script Host Engine – теоретически крайне нестандартным и, соответственно, потенциально являющимся индикатором угрозы.
Данный метод известен как Random Walk With Restart (далее – RWWR, случайный обход с перезапуском) и является вариацией ныне легендарного PageRank-алгоритма ранжирования Google.
Давайте рассмотрим кусок скрипта, который я написал для подсчёта этих рангов:

#lets build a row
$row= @(0)*$g.vertices.count
$w=0

foreach($e in $start.getEdges()) {    #calculate total frequency
    $w+=$e.weight
}
if ($w -eq 0)  {   #make it connected
$row[$ix] =1
}
else {  #we assign probabilitys
    #now create transition probability
    foreach($e in $start.getEdges()) {
        $ev = $e.endVertex
        $p = $e.weight
        $jx = v-index $ev.value.Key
        $row[$jx]= $p/$w #normalize by dividing by total
    }
}
$P[$ix] = $row  #yay! One row added to transition matrix

Для каждой вершины я рассчитываю итоговую частоту всех соседей и затем назначаю вероятность каждого перехода через нормализацию по суммарному значению. Таким образом, если PowerShell.exe имеет 20 визитов ко всем его соседям, но nc.exe только однажды посещалось от вершины PowerShell.exe, то вероятность перехода будет составлять 1/20 или 0.05. Логично?

Сложность заключается в расчёте матрицы, применяемой в RWWR, но для тех, кто посещал уроки вероятностного моделирования, данная процедура не составит труда. Есть неплохая обзорная статья на этот счёт на сайте Medium.

Мой скрипт, который я называю random-rater, ранжирует и выводит 10 наименьших значений из списка. Таким образом можно получить приложения, которые имеют наименьшую вероятность быть запущенными, начиная от заданной вершины графа угроз. Вот результат, если взять в качестве исходной точки PowerShell.exe:

Алгоритм Random Walk With Restart может выдавать гугл-подобное ранжирование угроз. Хммм, whoami имеет наименьшую вероятность быть запущенной


Алгоритм Random Walk With Restart может выдавать гугл-подобное ранжирование угроз. Хммм, whoami имеет наименьшую вероятность быть запущенной


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

Язык EQL (Event Query Language) для анализа угроз


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

Для тех, кто хочет погрузиться в тематику обнаружения угроз, но при этом не хочет работать с моими скриптами — я понимаю! — существует Event Query Language , или EQL. Это проект с открытым кодом, позволяющий применять язык запросов к журналу Sysmon, и о котором вы можете узнать более подробно из чрезвычайно всеобъемлющего поста. EQL не только отлично подходит для расследования инцидентов, но и может быть использован как инструмент при условии, что у вас есть какая-никакая свежая копия лога Sysmon.

Набор EQL предоставляет обработчик событий, преобразующий лог в удобоваримый JSON. Вы можете ознакомиться с копией моей ветки на GitHub. В отличие от моего статичного show-threat-path PS-скрипта, EQL позволяет вам делать запросы на лету.

Допустим, что меня заинтересовали все шеллы cmd.exe, которые были запущены от лица scvhost.exe, — это может являться признаком использования атакующим psexec.exe или smb.exe. Запрос будет выглядеть следующим образом:

Использование EQL для поиска шеллов cmd.exe, запущенного от svchost.exe. Кстати, jq – это Linux-утилита для отображения JSON данных


Использование EQL для поиска шеллов cmd.exe, запущенного от svchost.exe. Кстати, jq – это Linux-утилита для отображения JSON данных

Есть ещё более крутой и мощный способ получения данного результата через использование модификатора “потомка”. Такой EQL запрос позволяет искать по всем процессам с указанным предком, где угодно в иерархии. Например, вы можете искать приложения, которые, скажем, имели в качестве предка процесс regsvr32.exe и могли воспользоваться широко известной уязвимостью, о которой я рассказывал здесь.

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

Заключительные мысли о DIY-решениях для выявления угроз


Я обещал загрузить репозиторий Sysmon со всеми скриптами обнаружения угроз, описанными в этой статье. Периодически заглядывайте на мой GitHub , так как я со временем буду добавлять новые PS-утилиты на базе графов для выявления угроз вместе с дополнительной документацией – слишком много информации для раскрытия в одной статье.
Вы добрались до этого места, поздравляю!

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

Другим более важным выводом из всей статьи будет осознание того, что производители решений корпоративного уровня не только используют куда более сложные технологии выявления угроз, чем те, которые ИТ-разработчик способен написать в своё свободное время, но и приспособленность этих решений для работы с трафиком уровня крупной организации. Конечно, использование DIY-решений для анализа недоиспользуемого сервера или дополнительной валидации работы корпоративных продуктов является хорошей идеей. Но анализ угроз и их выявление действительно является проблемой больших данных, и, очевидно, это не та задача, которую способен решить PowerShell.

Если вас заинтересовала возможность побольше узнать о том, как Varonis справляется с задачей анализа и выявления угроз, вы всегда можете запросить персональную демонстрацию.
Теги:sysmonвыявление угрозpowershellанализ графовeql
Хабы: Блог компании Varonis Systems Информационная безопасность Системное администрирование PowerShell Big Data
+4
856 12
Комментировать
▇▅▄▅▅▄ ▇▄▅
Информация
Дата основания

1 мая 2005

Численность

1 001–5 000 человек

Дата регистрации

4 февраля 2015

Блог на Хабре