Читать книгу "Идём по киберследу: Анализ защищенности Active Directory c помощью утилиты BloodHound"
Автор книги: Дмитрий Неверов
Жанр: Компьютеры: прочее, Компьютеры
Возрастные ограничения: 16+
сообщить о неприемлемом содержимом
Информация
Названия связей берутся из файла
AddEdgeModal.jsx, расположенного вsrccomponentsModals.
Обновить запрос (Refresh Query) – заставляет BloodHound заново выполнить запрос.
Список узлов
Завершим раздел полезной функцией. Если граф очень большой, можно вывести список узлов, нажав пробел, в результате появится окно со списком (рис. 2.29).

Рис. 2.29. Список узлов
Список узлов поддерживает поиск и при вводе букв будет фильтровать данные, но, в отличие от формы поиска, не поддерживает поиск по objectid.
Рядом с каждым именем есть иконка, обозначающая метку узла. В колонке Collapse Info показывается, в какую группу собраны узлы.
Чтобы закрыть список узлов, нужно повторно нажать на пробел.
База данных neo4j
Neo4j – это графовая база данных. Ее модель проста и основана на узлах и связях.
Модель описывается следующим образом:
● Каждый узел может иметь различные связи с другими узлами.
● Каждая связь может переходить от одного узла к другому или к тому же узлу.
● Каждая связь может иметь или не иметь направление.
● Узлы и связи могут иметь свойства, а каждое свойство имеет имя и значение.
Версия neo4j Community Edition имеет очень ограниченный функционал, и из него мы будем использовать только создание резервных копий и восстановление данных из резервных копий.
Работать с информацией из базы данных можно с помощью браузера neo4j, консольного приложения cypher-shell, расположенного в директории $NEO4J_HOME/bin, или с помощью API.
Если необходимо подробнее изучить сам neo4j, то лучше обратиться к специальной литературе, мы же используем возможности языка запросов Cypher.
Интерфейс браузера neo4j
BloodHound выводит результаты запросов в виде графа или отдельных узлов. Свойства узлов можно увидеть во вкладке Node Info, а просмотр свойств связей вообще недоступен. Браузер neo4j в этом плане более гибкий, можно выводить информацию в различных видах. В основном мы будем использовать графы и таблицы.
После смены пароля мы оставили браузер neo4j, теперь стоит к нему вернуться и рассмотреть более детально.

Рис. 2.30. Браузер neo4j
Меню
Слева располагается меню, при нажатии на любой элемент раскрывается дополнительное поле.
Меню достаточно простое и не имеет сложных элементов. Мы рассмотрим только Информацию о базе данных (Database), Избранные запросы (Favorites) и Настройки браузера (Browser Settings), которые могут оказаться полезными. В большинстве случаев с остальными элементами вряд ли придется столкнуться во время использования.

Рис. 2.31. Меню браузера neo4j
Информацию о базе данных (Database)
Первый раздел – Информация о базе данных (Database) – содержит информацию о базе данных и о том, какие элементы входят в нее.
● Используемая база данных (Use database). Как говорилось ранее, в версии community edition есть всего одна база neo4j кроме system.
● Метки узлов (Node Labels) – этот пункт показывает, какие в базе есть метки. Каждая метка интерактивная, можно нажать на любую метку и получить результат. Вывод ограничен 25 узлами.
● Типы связей (Relationship Types) – аналогично с метками, показывает, какие связи есть в базе данных, и тоже интерактивно.
● Названия свойств (Property Keys) – показывает, какие свойства есть у узлов и связей.
● Подключение от имени какой учетной записи (Connected as) – в нашем случае у нас одна учетная запись с именем neo4j без определения ролей.
● DMBS – информация о СУБД.
Избранные запросы (Favorites)
Раздел Избранные запросы (Favorites) позволяет сохранять запросы, которые затем можно использовать. К сожалению, в браузере neo4j есть функция экспорта запросов, но нет импорта. Как добавить и использовать этот функционал, мы рассмотрим дальше.
Настройки браузера (Browser Settings)
Раздел Настройки браузера (Browser Settings) содержит несколько подразделов, которые позволяют сделать работу с браузером удобнее.
Интерфейс пользователя (User Interface)

Рис. 2.32. Интерфейс пользователя
Интерфейс пользователя (User Interface) позволяет:
● изменить тему внешнего вида;
● объединить некоторые символы в один (Code font ligatures) – это касается только стрелок направления связи;
● включить редактор нескольких запросов (Enable multi statement query editor) – браузер neo4j поддерживает выполнение нескольких запросов, которые разделяются точкой с запятой. Отключение этой функции не позволит выполнять такие запросы.
Предпочтения (Preferences)

Рис. 2.33. Предпочтения
Данный раздел содержит две настройки:
● Первоначальная команда для выполнения (Initial command to execute) – команда, которая будет выполняться при запуске браузера neo4j. Команды начинаются с двоеточия. Например, можно вызывать историю команд :history или подсказку по командам :help.
● Таймаут подключения в миллисекундах (Connection timeout (ms)) – определяет, сколько времени браузер будет ожидать при подключении к базе данных.
Рамки с результатами (Result Frames)

Рис. 2.34. Рамки с результатами
В результате запроса Cypher в браузере neo4j создается отдельная рамка со строкой запроса и результатом. Данный раздел определяет следующие параметры:
● Максимальное количество рамок с результатами (Maximum number of result frames) – задает количество новых рамок с запросами, при превышении которого старые будут удаляться.
● Максимальная длина истории (Max history length) – задает количество запросов в истории, после чего они будут затираться. Историю можно вызвать командой :history.
Визуализация графа (Graph Visualization)

Рис. 2.35. Настройки визуализации графа
В данном разделе определяются настройки визуализации графа:
● Количество узлов при отображении графа (Initial Node Display) – определяет максимальное количество узлов при отображении графа.
● Максимальное количество соседей (Max neighbours from vis interaction) – определяет максимальное количество соседних узлов для одного узла.
● Максимальное количество строк для просмотра (Result view max rows) – максимальное количество строк в результате для просмотра в режиме таблицы или текста.
● Максимальное количество полей (Max record fields) – максимальная длина возвращаемого списка. Если длина списка будет превышена, будут выданы только первые записи, а остальные будут отброшены.
● Связи результирующих узлов (Connect result nodes) – отображает все связи между узлами, полученными в результате запроса, даже те, которые не были запрошены.
● Показывать подсказку использования масштабирования (Show zoom interactions hint) – при включенном параметре, если граф получается большим, всплывает окно с подсказкой, как можно пользоваться масштабированием.
Настройки можно посмотреть с помощью команды :config.

Рис. 2.36. Результат выполнения команды :config
Кроме того, с помощью этой команды можно изменять значения параметров. Например, чтобы увеличить количество записей в истории, нужно выполнить следующую команду:
:config maxHistory:50
Рабочая область
Справа от меню расположена рабочая область, которая состоит из двух элементов:
● главная строка запроса;
● рамки выполненных запросов (рис. 2.37).

Рис. 2.37. Рабочая область
Главная строка запроса

Рис. 2.38. Главная строка запроса
Главная строка запроса состоит из следующих элементов:
● Поле ввода запросов или команд (поддерживает многострочные запросы, для перехода на новую строку используется сочетание клавиш Shift + Enter).
● Кнопка Выполнить (Run) предназначена для выполнения запроса или команды. То же самое можно сделать клавишами Enter или CTRL + Enter для многострочных запросов.
● Кнопка Полноэкранный режим (Fullscreen) разворачивает строку запроса в полноэкранный режим.
● Кнопка Очистить (Clear) очищает строку запроса.
Пролистывать предыдущие запросы можно с помощью стрелок вверх и вниз, для многострочных запросов – в сочетании с клавишей Shift.
Получить историю можно с помощью команды :history.

Рис. 2.39. Вызов истории выполненных запросов
Данная команда покажет последние 30 запросов, данный параметр определяется в настройке Max history length. Нажатие на любой из запросов вставит его в главное окно запросов.
Рамки (Frame)
Каждый выполненный запрос в главной строке запроса открывает отдельную область. По умолчанию neo4j открывает 15 таких областей, но их количество может быть изменено в параметре Maximum number of result frames. Команда :clear удалит все рамки из рабочей области.

Рис. 2.40. Рамка с результатами запроса
Элементы управления рамкой
В правом верхнем углу расположены элементы управления рамкой:

Рис. 2.41. Элементы управления рамкой
● Кнопка Закрепить наверху (Pin at top) позволяет закрепить рамку под основной строкой запроса, все последующие запросы будут располагаться под ней.
● Кнопка Свернуть (Collapse) сворачивает рамку, оставляя только строку запроса.
● Кнопка Полноэкранный режим (Fullscreen) разворачивает рамку на все окно браузера.
● Кнопка Закрыть (Close) закрывает текущую рамку.
Строка запроса

Рис. 2.42. Строка запроса в рамке
Строка запроса работает так же, как и основная. Позволяет работать с графом, не запуская новую рамку.
Следующая кнопка Сохранить как Избранное (Save as Favorite) позволяет добавить запрос в избранные.
Прежде чем это сделать, лучше добавить перед командой комментарий с кратким описанием того, что она делает, выполнить ее и после уже добавлять в избранные.

Рис. 2.43. Добавление запроса в избранное
Заключительный элемент поля запроса – кнопка Экспорт (Exports) – позволяет экспортировать результаты запроса в другие типы файлов. Варианты экспорта зависят от выбора вывода информации:
● граф – в виде картинки в формате SVG или PNG;
● таблица, текст, код – в текстовом виде в формате JSON или CSV.
Формат вывода информации
Слева от поля вывода располагаются варианты отображения информации.
● Граф (Graph) – визуальное построение графа с узлами и связями.
● Таблица (Table) – табличное представление данных при запросе свойств узлов и связей или в виде форматированного JSON при запросе графа.
● Текст (Text) – представление данных в неформатированном виде.
● Код (Code) – представление данных в виде HTTP-запроса и ответа в формате JSON.

Рис. 2.44. Формат вывода результатов
В большинстве случаев браузер neo4j автоматически выбирает режим между графом и текстом.
Поле вывода

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

Рис. 2.46. Изменение внешнего вида узла
Масштабирование
При выводе информации в виде графа в правом нижнем углу появляется управление масштабированием графа со следующими функциями:
● увеличение;
● уменьшение;
● выравнивание и отцентровка всего графа.

Рис. 2.47. Управление масштабом графа
Установка плагинов
Neo4j имеет большое количество различных плагинов, которые позволяют улучшить работу с запросами. В книге используется только базовый APOC, поэтому рассмотрим установку плагинов на его примере.
Зайдем на официальный GitHub neo4j с плагинами[10]10
https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/4.4.0.1
[Закрыть] и скачаем двоичный jar-файл apoc-4.4.0.1-all.jar. Поместим его в папку $NEO4J_HOME/plugins. В моем случае это C: ToolsNeo4jplugins.
Информация
Поскольку APOC использует внутренние API neo4j, необходимо использовать правильную версию APOC для вашей установки neo4j. APOC использует согласованную схему управления версиями:
<neo4j-версия>.<apoc>версия. Завершающая часть номера версии<apoc>будет увеличиваться с каждым новым выпуском APOC.
Если сейчас мы перезагрузим neo4j и попытаемся воспользоваться процедурами из плагина, то получим ошибку.

Рис. 2.48. Ошибка некорректной настройки процедур
Чтобы исправить ее, нужно открыть файл конфигурации $NEO4J_HOME/conf/neo4j.conf на редактирование. Убрать комментарий со строки dbms.directories.plugins=plugins, затем найти строку dbms.security.procedures.unrestricted=…, после нее добавить строку dbms.security.procedures.unrestricted=algo.*, apoc.* и перезапустить службу:
C: ToolsNeo4jbinneo4j.bat restart
В дальнейшем мы столкнемся с процедурами из этого плагина, а пока перейдем к другой теме.
Создание резервных копий и восстановление
Создание резервных копий полезно при переносе базы данных с одного компьютера на другой или при сохранении результатов проекта для будущих исследований. При дальнейшем изучении книги мы будем несколько раз обращаться к резервным копиям.
Чтобы создать резервную копию, нам необходимо остановить базу данных. Для этого перейдем в директорию $NEO4J_HOME/bin и выполним команду:
.neo4j.bat stop
Если neo4j запущен в режиме консоли, то можно нажать Сtrl+С или просто закрыть окно.
Теперь создадим резервную копию текущей базы данных, указав имя базы данных neo4j и путь до файла резервной копии:
.neo4j-admin.bat dump -database="neo4j" -to="c: toolsneo4j.dump"
После успешного завершения создания резервной копии запустим neo4j:
.neo4j.bat start

Рис. 2.49. Создание резервной копии
Процедура восстановления похожа на создание копий, изменяется только команда с dump на load. Останавливаем neo4j:
.neo4j.bat stop
Выполняем команду восстановления данных из дампа, указав полный путь до файла дампа, созданного ранее:
.neo4j-admin.bat load -database="neo4j" -from="c: toolsneo4j.dump" -force
Стоит обратить внимание на использование ключа -force: в случае его отсутствия neo4j сообщит, что база данных neo4j уже существует.

Рис. 2.50. Сообщение об ошибке
После успешного восстановления из резервной копии запустим neo4j:
.neo4j.bat start

Рис. 2.51. Успешное восстановление данных
03. Дрессируем собаку. Язык запросов Cypher
SharpHound, BloodHound и neo4j – это инструменты для сбора, хранения и визуализации информации. Основная магия – это язык запросов Cypher. В интернете можно найти уже готовые запросы и использовать их, но в дополнение к этому хорошо бы разбираться, как они работают, и уметь разрабатывать их самому. В этом разделе мы рассмотрим основные принципы построения запросов и синтаксис языка запросов Cypher.
Обычно результаты запросов представляются в виде графов, что удобно для обнаружения связей между объектами. В некоторых случаях данные могут представляться в виде таблиц, что удобно для анализа данных. В BloodHound объекты домена являются вершинами (узлами) графа, а отношения (связи) между этими объектами – ребрами. Также в neo4j узлы графа маркируются меткой (label) по общему принципу. Это позволяет делать выборку только из необходимой группы объектов. Названия связей определяются по типу (type).
Совет
Так как некоторые части зависят от других и на первом этапе могут быть не очень понятными, то рекомендую прочитать этот раздел от начала до конца, а потом вернуться уже с пониманием некоторых моментов.
Основные принципы
Cypher представляет собой удобочитаемый и мощный декларативный язык запросов, и главное – понять логику их составления. У нас есть начальный узел и конечный, которые соединены между собой связью. Этот граф является шаблоном, по которому будет выполняться выборка из базы данных.

Рис. 3.1. Простой граф
Каждый узел в neo4j обладает определенными параметрами:
● Идентификатор (ID) – это обязательный параметр порядкового номера узла.
● Метка (Label) – необязательный, но важный параметр, позволяет объединять узлы по определенному признаку. Например, User или Computer.
● Свойства (Properties) – необязательный параметр, например objectid или distingueshedname. Данный параметр придает каждому узлу индивидуальность. На основании свойств можно сужать выборку данных или получать узлы, имеющие общие свойства.
Связь также имеет свои параметры:
● Идентификатор (ID) – обязательный параметр порядкового номера связи.
● Название (Type) – не обязательный, но важный параметр, позволяет объединять узлы по определенному признаку. Например, MemberOf или GenericAll.
● Свойства (Properties) – необязательный параметр. Данный параметр придает каждой связи индивидуальность. В BloodHound связи обладают разными свойствами, например isacl и isinherited. В дальнейшем мы тоже будем добавлять различные свойства связям.
Общий вид запроса выглядит следующим образом:

Рис. 3.2. Общий вид запроса
В качестве операторов могут выступать:
● CREATE и MERGE – создание нового элемента;
● MATCH – выполнение выборки;
● RETURN – возврат результата (может быть как в начале, так и в конце запроса);
● DELETE – удаление узла или связи (может быть как в начале, так и в конце запроса).
Другие операторы:
● SET и REMOVE – добавление или удаление свойств;
● WHERE – добавление условия к шаблону.
Внимание
Необходимо запомнить, что Cypher чувствителен к регистру. Это важно для названий меток и связей, названий и значений свойств, но операторов это правило не касается.
Возвращаясь к рисунку 3.2, получаем следующий формат: на первом месте идет оператор MATCH, MERGE и др., следующим – начальный узел, затем название связи (опционально), конечный узел, условия (опционально), и завершается запрос оператором RETURN. В некоторых случаях оператор RETURN может опускаться, например при добавлении свойства узлу, или заменяться оператором WITH, если необходимо изменить область видимости.
Стрелки определяют направление и могут быть направлены как слева направо, так и в обратную сторону. Изменение направления стрелок может быть полезно при составлении запроса. Например, мы хотим узнать, на каких компьютерах у пользователя есть сессия. По правилам BloodHound связь HasSession устанавливается от компьютера к пользователю.

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

Рис. 3.4. Стрелка справа налево
Два шаблона абсолютно идентичны, разница только в интерпретации вопроса и удобстве чтения.
Внимание
В Cypher нет двунаправленных стрелок, но могут быть запросы, где направление не указано.
В браузере neo4j есть справочник по командам и операторам. Получить справку по операторам можно с помощью команды :help:
:help <Оператор>
:help MATCH

Рис. 3.5. Справка по оператору MATCH
Оператор MATCH
Для поиска по базе в neo4j используется оператор MATCH, следом идет шаблон поиска, условия выборки с помощью оператора WHERE, и завершается запрос выводом результатов RETURN.

Рис. 3.6. Оператор MATCH
Наша задача – создать правильный шаблон с добавлением условий. Неверно составленный запрос выдаст неверную информацию.
Рассмотрим простой запрос Cypher, где будут выбираться пользователи, у которых есть права локального администратора на компьютеры:
MATCH (u: User)-[r: AdminTo]->(c: Computer) RETURN u,r,c
Здесь переменным u, r и c будут передаваться результаты выборки, это не обязательно, если не нужно выделять какие-то особые условия, но для возврата данных все равно нужно определить переменную. Такой запрос нельзя профилировать и оптимизировать, а если добавить еще несколько узлов и связей, то перечисление будет требовать дополнительных затрат.
Выходом из этой ситуации будет назначить общую переменную для всего запроса. Запрос приобретет следующий вид.

Рис. 3.7. Добавление общей переменной в запрос
Если выполнить измененный запрос, то результат будет аналогичным:
MATCH p=(:User)-[: AdminTo]->(:Computer) RETURN p
Различные варианты использования оператора RETURN мы рассмотрим позже.
Указание метки будет влиять на скорость выполнения запроса, но и результат может быть другим. Например, в запросе выше упускается тот факт, что группы тоже могут иметь связь CanRDP. Таким образом, в запросе можно опустить указание метки User, и он будет выглядеть следующим образом:
MATCH p=(u)-[r: AdminTo]->(c: Computer) RETURN p
Варианты запросов
Cypher – достаточно свободный язык запросов, одинаковых результатов можно добиться разными путями. Рассмотрим выполнение запроса выше другими способами. Мы можем отдельно определить начальный и конечный узлы и затем запросить, есть ли между ними связь.
MATCH (u: User)
MATCH (c: Computer)
MATCH p=(u)-[r: AdminTo]->(c) RETURN p
Все это можно записать в одну строчку, но для удобства чтения сложные запросы лучше записывать в несколько строк.
И этот запрос можно оптимизировать, оставив только первый MATCH и после каждой строчки поставив запятую.
MATCH (u: User),
(c: Computer),
p=(u)-[r: AdminTo]->(c) RETURN p
Браузер neo4j пометит, что данный запрос не очень удачный и его обработка может потребовать больше времени и ресурсов, тем не менее задача будет выполнена.
Объединение связей
Запрос может быть сложным: первым шагом мы можем запросить один шаблон, вторым – уже другой. Самый обычный пример для BloodHound – это поиск различных прав через членство в группах.

Рис. 3.8. Двухэтапный запрос
Возьмем все тот же пример с правами локального администратора. Посмотрим, какие группы имеют права локального администратора и какие пользователи входят в эти группы.
Информация
В сложных запросах стоит идти от конечной цели (последнего запроса) к начальному узлу.
MATCH p=(u: User)-[: MemberOf]-(g: Group)-[: AdminTo]->(c: Computer) RETURN p
Внимание
Данный запрос не вернет информацию, если пользователь имеет права локального администратора напрямую.
Мы можем объединить связи в этом запросе, используя логический оператор ИЛИ (представлен как |).
MATCH p=(u: User)-[: MemberOf|AdminTo]->(c: Computer) RETURN p
Синтактически этот запрос верен, но он будет искать только прямые связи и не учитывать, что группа может являться членом другой группы. Поэтому нужно добавить количество промежуточных узлов, к которому будет применяться данный шаблон.

Рис. 3.9. Объединение связей
И тогда наш запрос примет вид
MATCH p=(u: User)-[: MemberOf|AdminTo*1..]->(c: Computer) RETURN p
В предыдущем примере мы использовали запись *1.. – указание количества промежуточных узлов, к которым может применяться шаблон, в данном случае – от одного перехода до бесконечности. Число переходов здесь – это количество различных промежуточных узлов от начального узла до конечного.
Ниже приведены две таблицы, в которых описаны различные варианты синтаксиса.
Без указания типа связи:

Приведу несколько примеров. Все прямые связи между узлами:
MATCH p=(u: User)->(c: Group) RETURN p
MATCH p=(u: User)-[]->(c: Group) RETURN p
Все непрямые связи между узлами с указанием ограничений от одного до двух переходов:
MATCH p=(u: User)-[*1..2]->(c: Group) RETURN p
С указанием типа связей:

Пример – получить всех пользователей и их членство в группах:
MATCH p=(u: User)-[: MemberOf*1..]->(g: Group) RETURN p
Другой пример – получить все компьютеры, где пользователи являются локальными администраторами:
MATCH p=(u: User)-[: MemberOf|AdminTo*1..]->(c: Computer) RETURN p
Короткие пути
Построение графа со всеми непрямыми связями потребует большого количества ресурсов, и, скорей всего, база не выдержит и упадет. Для решения этой проблемы можно использовать операторы ShortestPath и AllShortestPaths. Разница между ними в том, что первый находит один короткий путь, а второй – все, при условии, что они существуют.
Для использования коротких путей необходимо поместить шаблон в круглые скобки. Так, предыдущий пример будет выглядеть следующим образом:
MATCH p=ShortestPath((u: User)-[*1..]->(c: Group)) RETURN p
Совет
Ограничение количества переходов поможет найти самые короткие пути.
В интерфейсе BloodHound в форме Поиск путей (Pathfinding) используется оператор AllShortestPaths, который применяется для поиска коротких путей между двумя указанными узлами.
Внимание! Это не конец книги.
Если начало книги вам понравилось, то полную версию можно приобрести у нашего партнёра - распространителя легального контента. Поддержите автора!