Идём по киберследу: Анализ защищенности Active Directory c помощью утилиты BloodHound — страница 14 из 46

ON CREATE SET
, которая добавляет свойства узла при его создании. Однако при этом придется передать индивидуальный идентификатор.

MERGE (m: User {sid: "U-003"})

ON CREATE SET

m.name='TEST'

В BloodHound уникальный идентификатор – свойство

sid
, и neo4j будет проверять его на совпадение, если такого узла нет, то создаст его, а после создания добавит переданные свойства.

Если мы сейчас выполним запрос пользователей, у которых есть свойство

sid
, из базы, то получим три узла с одинаковым именем, но с разными идентификаторами.

MATCH(u: User) WHERE u.sid IS NOT NULL RETURN u.name,

u.sid


Рис. 3.44. Проверка создания узлов


Добавление свойств при совпадении

Кроме

ON CREATE SET
в
MERGE
есть функция
ON MATCH SET
, которая добавляет свойства к ранее созданному узлу, попадающему под определенные условия. Если узла не существует, то он будет создан, с указанным идентификатором, но без свойств.

MERGE(m: User {sid: "U-004"})

ON MATCH SET

m.name='TEST'

RETURN m.name, m.sid


Рис. 3.45. Результат выполнения запроса


Но стоит повторить этот запрос, и появится свойство

name
.


Рис. 3.46. Результат повторного выполнения запроса


С функцией

ON MATCH SET
нужно быть аккуратным, в случае неверно созданного запроса данные изменятся необратимо. Вот пример неправильного запроса:

MERGE(m: User)

ON MATCH SET

m.sid='U-005'

RETURN m.name, m.sid

При выполнении этого запроса у всех узлов с меткой

User
свойство
sid
станет одинаковым.

Оператор DELETE

Узел можно удалить с помощью оператора

DELETE
.


Рис. 3.47. Оператор DELETE


Запрос выполняется в два этапа: сначала поиск узлов по условиям, затем удаление. Метка и свойства – необязательные параметры, они дают более точный критерий удаления.

Внимание

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

Создадим элементы, отличные от созданных ранее. В качестве метки будем использовать

Computer
.

MERGE (m: Computer {name: "COMP1", sid:'C-001'})

MERGE (n: Computer {name: "COMP2", sid:'C-002'})

MERGE (s: Computer {name: "COMP2", sid:'C-003'})

MERGE (s: Computer {name: "COMP3", sid:'C-004'})

MERGE (s: Computer {name: "COMP4", sid:'C-005'})

Внимание

Мы создали два узла с одинаковым именем, и это не опечатка.

Теперь начнем выполнять удаление по разным критериям. Сначала удалим узел, который имеет определенный идентификатор:

MATCH (m: Computer {sid:'C-001'}) DELETE m

Удаление узлов по общему свойству:

MATCH (m: Computer {name:'COMP2'}) DELETE m

Удаление узлов по общей метке:

MATCH (m: Computer) DELETE m

Удаление всех узлов:

MATCH (m) DELETE m

Можно удалить узел и все связи, которые он имеет. В этом случае запрос Cypher будет выглядеть следующим образом:

MATCH (n: User {name: "USER@DOMIAN.LOCAL"})

DETACH DELETE n

Создание связей

В предыдущем разделе мы удалили все узлы, и теперь нам нужно создать несколько новых узлов:

MERGE (u1:User {name: "USER"})

MERGE (u2:User {na

me: "ADMIN"})

MERGE (g: Group {name: "GROUP"})

MERGE (c1:Computer {name: "COMP"})

MERGE (c2:Computer {name: "SERVER"})

Проверим, что все узлы создались корректно:

MATCH (n) RETURN n

В результате у нас есть два пользователя, одна группа и два компьютера.

Связь между узлами создается с помощью оператора

MERGE
. Данный оператор будет проверять существование связи, и в случае ее отсутствия она будет создана. Можно использовать
CREATE
, но все с тем же условием, что связь должна быть уникальной. Общая схема создания связи будет следующей:


Рис. 3.48. Схема создания связи


Для начала мы определяем начальный и конечный узлы с помощью оператора

MATCH
. После этого уже создаем связь, определяя направление. Также можно указать свойства связи при необходимости.

Если выполнить только

MERGE
, то сначала будут созданы узлы, а затем установлена связь. Такой вариант можно использовать, но с соблюдением всех условий.

Сейчас будем создавать связи между созданными узлами. Будем использовать принятые в BloodHound типы связей.

Пользователь

USER
имеет членство в группе
GROUP
. Запрос Cypher будет следующим:

MATCH (u: User {name: "USER"})

MATCH (g: Group {name: "GROUP"})

MERGE (u)-[r: MemberOf]->(g)

Группа

GROUP
имеет привилегии локального администратора на компьютере
COMP
:

MATCH (g: Group {name: "GROUP"})

MATCH (c: Computer {name: "COMP"})

MERGE (g)-[r: AdminTo]->(c)

Пользователь

ADMIN
имеет права
GenericAll
на пользователя
USER
и права локального администратора на компьютере
SERVER
. Также добавим связи
GenericAll
свойство
isacl
в значении
TRUE
:

MATCH (u1:User {name: "ADMIN"})

MATCH (u2:User {name: "USER"})

MATCH (c: Computer {name: "SERVER"})

MERGE (u1)-[r1:GenericAll]->(u2) SET r1.isacl = TRUE

MERGE (u1)-[r2:AdminTo]->(c)

Теперь можно выполнить проверку всего, что у нас получилось. Если в настройках браузера neo4j установлен флаг Connect result nodes, то будет достаточно выполнить следующий запрос:

MATCH (n) RETURN n

Или создать полный запрос:

MATCH p=(n)-[r: AdminTo|MemberOf|GenericAll]->(m) RETURN p


Рис. 3.49. Результат добавления связей между узлами


Как можно увидеть, задача не очень сложная, но при наличии большого количества объектов и связей она будет кропотливой. Любая ошибка приведет к неверному толкованию.

Удаление связей

Как и узлы, связи удаляются с помощью оператора

DELETE
.


Рис. 3.50. Схема удаления связей


Для начала выбирается шаблон поиска, а затем выполняется удаление связи между узлами.

Совет

Для корректного удаления связи между узлами сначала можно выполнить

RETURN
, а затем уже
DELETE
.

Рассмотрим несколько примеров. Удаление одной связи по ее наименованию:

MATCH (m)-[r: MemberOf]->(n) DELETE r

Удаление двух и более связей по их наименованию:

MATCH (m)-[r: MemberOf|GenericAll]->(n) DELETE r

Удаление связи по ее свойству:

MATCH (m)-[r]->(n) WHERE r.isacl = TRUE DELETE r

Удаление любых связей между двумя узлами:

MATCH (m)-[r]->(n) DELETE r

Удаление цепочки узлов и связей

В моей практике не требовалось удалять целую цепочку узлов и связей, но возможность такая существует. Достаточно передать запрос в переменную, а затем удалить ее:

MATCH p=(n)-[*1..]-(m: Computer {name: "COMP"}) DELETE p

Очистка базы

Теперь, когда появилось понимание, как создавать и удалять узлы и связи, можно завершить эту часть очисткой базы от всех узлов с их связями. Запрос Cypher достаточно простой:

MATCH (n)

DETACH DELETE n

Загрузка информации в базу данных

Перед использованием информации ее необходимо загрузить в базу данных. BloodHound использует результаты работы SharpHound, которые формируются в виде JSON определенного типа, поэтому разные версии BloodHound не принимают результаты от других версий SharpHound.