October 1

Из непроходимых ребер в проходимые

В статье мы уже обсуждали ребра LocalToComputer и MemberOfLocalGroup и научились включать и исключать их в Cypher запрос для получения проходимого графа. Запрос выполняет свою задачу, но получается достаточно громоздким. Чтобы сделать запрос более удобным мы можем вернуться к привычным ребрам AdminTo, CanRDP и так далее.

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

MATCH (g)-[:LocalToComputer]->(c:Computer) WHERE g.objectid ENDS WITH '-544'
MATCH (p)-[:MemberOfLocalGroup]->(g) WHERE NOT (p)-[:AdminTo]->(c)
MERGE (p)-[:AdminTo {isacl:false}]->(c);

В этом запросе мы сначала ищем локальную группу с определенным RID (в данном случае это группа Administrators на компьютере), и которая связана с компьютерами, второй MATCH ищет всех прямых членов этой группы, но при этом между этим объектом и компьютером нет прямой связи. И последним шагом мы создаем новую связь AdminTo. В результате мы получим уже прямую связь от одного узла до другого.

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

Можно пойти другим путем и объединить все в один Cypher запрос:

MATCH (g:ADLocalGroup)-[:LocalToComputer]->(c:Computer)
WHERE g.objectid =~ '(?i).*(-544$|-555$|-562$|-580$)'
MATCH (p)-[:MemberOfLocalGroup]->(g)
WITH p, c, g,
     CASE
       WHEN g.objectid ENDS WITH '-544' THEN 'AdminTo'
       WHEN g.objectid ENDS WITH '-555' THEN 'CanRDP'
       WHEN g.objectid ENDS WITH '-562' THEN 'ExecuteDCOM'
       WHEN g.objectid ENDS WITH '-580' THEN 'CanPSRemote'
     END AS relType
FOREACH (_ IN CASE WHEN relType = 'AdminTo' THEN [1] ELSE [] END |
  MERGE (p)-[:AdminTo {isacl:false}]->(c)
)
FOREACH (_ IN CASE WHEN relType = 'CanRDP' THEN [1] ELSE [] END |
  MERGE (p)-[:CanRDP {isacl:false}]->(c)
)
FOREACH (_ IN CASE WHEN relType = 'ExecuteDCOM' THEN [1] ELSE [] END |
  MERGE (p)-[:ExecuteDCOM {isacl:false}]->(c)
)
FOREACH (_ IN CASE WHEN relType = 'CanPSRemote' THEN [1] ELSE [] END |
  MERGE (p)-[:CanPSRemote {isacl:false}]->(c)
)

Таким образом мы возвращаемся к привычным ребрам удаленного доступа без дополнительной фильтрации локальных групп.