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

Оператор сравнения

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

=.

Например, найти всех членов группы администраторов домена:

MATCH (u: User)-[r: MemberOf*0..]->(g: Group) g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name

Кроме строковых значений могут приниматься булевы значения

FALSE
и
TRUE
или числовые. Например, найти все незаблокированные учетные записи компьютеров:

MATCH (c: Computer) WHERE c.enabled = TRUE return c

Другой способ использовать точное вхождение – это указать фильтр запроса в узлах. Фильтр задается в фигурных скобках по шаблону

<свойство>:<значение>
. Например, определить, на каких машинах используется LAPS, можно следующим образом:

MATCH (c: Computer {haslaps: true}) return c

Можно добавить несколько условий. В таком случае они разделяются запятой. Например, выбрать только незаблокированные объекты и компьютеры, на которых используется LAPS.

MATCH (c: Computer {enabled: true, haslaps: true}) return c

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

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

MATCH (c) WHERE c: User RETURN c

Имя связи тоже можно указывать в

WHERE
. В данном случае используется
type()
, так как у связи нет свойства имени.

MATCH p=(c: Computer)-[r]->(u: User) WHERE type(r) = "HasSession" RETURN p

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

isacl
в значении
TRUE
:

MATCH p=(u: User)-[r]-(c: Computer) WHERE r.isacl = TRUE RETURN p

Оператор «не равно»

Оператор не равно

<>
противоположен предыдущему оператору. Например, найти все группы, которые не являются контроллерами домена:

MATCH (g: Group) WHERE g.name <>"DOMAIN CONTROLLERS@DOMAIN.LOCAL" RETURN g.name

Операторы арифметического сравнения

Операторы арифметического сравнения

>
(больше чем),
>=
(больше или равно),
<
(меньше чем) и
<=
(меньше или равно) используются для сравнения чисел. В BloodHound, наверное, нет числовых значений, кроме результатов работы с датами или сложных запросов с использованием подсчета. Примеры работы с датами будут рассмотрены далее.

Оператор NOT

Логический оператор отрицания

NOT
инвертирует условие. Например, при анализе атрибута
description
было обнаружено, что некоторые учетные записи имеют описание, связанное с заявками в Help Desk. Заявки имеют идентификационный номер, который администраторы иногда вносят в этот атрибут. Идентификационный номер часто имеет буквенный префикс (например, HDQ), задача состоит в том, чтобы исключить из вывода все такие записи.

MATCH(u: User) WHERE (NOT(u.description CONTAINS "HDQ")) RETURN u.name, u.description

Оператор

NOT
может применяться в сочетании с другими операторами. Например, с оператором сравнения:

MATCH (g: Group) WHERE NOT g.name = "DOMAIN CONTROLLERS@DOMAIN.LOCAL" RETURN g.name

Оператор IS NULL

Оператор нулевого значения

IS NULL
проверяет, что свойство не имеет значения. В качестве примера выполним поиск потенциальных пресозданных машин, часто такие машины имеют пустой атрибут
operatingsystem
:

MATCH (c: Computer) WHERE c.operatingsystem IS NULL RETURN c.name

Оператор IS NOT NULL

Оператор проверки на ненулевое значение

IS NOT NULL
противоположен предыдущему оператору и проверяет наличие значения в свойстве. По факту это объединение двух операторов –
NOT
и
IS NULL
. В качестве примера можно выполнить проверку непустого атрибута
description
для поиска в нем полезной информации:

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

Оператор CONTAINS

Оператор проверки вхождения

CONTAINS
проверяет наличие передаваемого значения в свойстве. Например, найти доменные группы, в имени которых встречается слово DBA (администраторы баз данных):

MATCH (g: Group) WHERE g.name CONTAINS "DBA" RETURN g.name

Другой пример – найти все хосты, где установлен Windows Server:

MATCH (c: Computer) WHERE c.operatingsystem CONTAINS 'Server' RETURN c.name

Оператор STARTS WITH

Строковый оператор

STARTS WITH
позволяет указывать префикс для значения свойства. Имеет смысл использовать для свойств имени – например, найти все учетные записи с префиксом ADM:

MATCH (u: User) WHERE u.name STARTS WITH "ADM" RETURN u.name

Оператор ENDS WITH

Строковый оператор

ENDS WITH
аналогичен предыдущему, но с указанием постфикса. Этот оператор удобно использовать для указания имени домена или RID. В качестве примера требуется подсчитать, столько учетных записей пользователей есть в домене
CHILD.DOMAIN.LOCAL
. Запрос в Cypher будет следующим:

MATCH (u: User) WHERE u.name ENDS WITH "CHILD.DOMAIN.LOCAL" RETURN count(u)

Или найти всех пользователей, входящих в группу доменных администраторов. В данном случае будем указывать не имя, а RID, который всегда одинаков и имеет значение 512:

MATCH (u: User)-[r: MemberOf]->(g: Group) WHERE g.objectid ENDS WITH '-512' RETURN u.name, g.name

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

Логические операторы OR и AND

При объединении условий фильтрации запросов можно использовать логические операторы

AND
и
OR
. Например, необходимо проверить, какие активные учетные записи будут входить в группу доменных администраторов. Запрос в Cypher будет следующим:

MATCH (u: User)-[r: MemberOf*0..]->(g: Group)

WHERE u.enabled=TRUE

AND g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name

Другой пример – узнать, какие пользователи входят в группу администраторов или доменных администраторов:

MATCH (u: User)-[r: MemberOf*0..]->(g: Group)

WHERE g.name = "ADMINISTRATORS@DOMAIN.LOCAL" OR g.name = "DOMAIN ADMINS@DOMAIN.LOCAL"

RETURN u.name, g.name

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

MATCH (n) WHERE n.owned = TRUE AND (n: User OR n: Computer) RETURN n

Оператор EXISTS

Оператор

EXISTS
может использоваться для проверки существования свойства или связи. Например, получить всех пользователей, у которых есть свойство
hasspn
, для выполнения техники Kerberoasting. Запрос в Cypher будет выглядеть следующим образом:

MATCH (u: User) WHERE EXISTS(u.password) RETURN u

Информация

Браузер neo4j считает использование

EXISTS
устаревшим, этот оператор будет удален в будущих версиях neo4j. Вместо
EXISTS
предлагается использовать
IS NULL.

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

MATCH (u: User) WHERE EXISTS {(u)-[r: GenericAll]->(g: Group)} RETURN u.name

Использование регулярных выражений

Оператор регулярных выражений

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

MATCH (g: Group) WHERE g.name =~ '(?i)domain user.*' RETURN g

Параметр

(?i)
сообщает, что регистр не учитывается.

В регулярном выражении можно использовать логическое ИЛИ в виде символа |, чтобы искать по нескольким значениям. Например, нужно посмотреть, есть ли в атрибуте

description
слова «пароль» или «password», тогда запрос в Cypher может иметь следующий вид: