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

Add-Content $OutFile "MATCH (m {objectid:'$ObjectID'}) MATCH (n: CA {objectid:'$ObjectGUID'}) MERGE (m)-[r: RequestCertificates]->(n) SET r.isacl=TRUE;"

}

# Проверяем права ManageCA

if($Object.AccessMask -band "1")

{

# Создаем Cypher-запрос на создание связи между шаблоном и объектом с правами ManageCA

Add-Content $OutFile "MATCH (m {objectid:'$ObjectID'}) MATCH (n: CA {objectid:'$ObjectGUID'}) MERGE (m)-[r: ManageCA]->(n) SET r.isacl=TRUE;"

}

# Проверяем права на управление шаблонами

if($Object.AccessMask -band "2")

{

# Создаем Cypher-запрос на создание связи между шаблоном и объектом с правами ManageCertificates

Add-Content $OutFile "MATCH (m {objectid:'$ObjectID'}) MATCH (n: CA {objectid:'$ObjectGUID'}) MERGE (m)-[r: ManageCertificates]->(n) SET r.isacl=TRUE;"

}

# Проверяем права на чтение шаблонов сертификатов

if($Object.AccessMask -band "256")

{

# Создаем Cypher-запрос на создание связи между шаблоном и объектом с правами Read

Add-Content $OutFile "MATCH (m {objectid:'$ObjectID'}) MATCH (n: CA {objectid:'$ObjectGUID'}) MERGE (m)-[r: Read]->(n) SET r.isacl=TRUE;"

}

}

# Получаем опубликованные сертификаты

$certTemplates = $ca.properties.certificateTemplates

foreach($certTemplate in $certTemplates)

{

$certTemplateName = $certTemplate.ToUpper()

# Создаем Cypher-запрос на создание связи между шаблоном и центром сертификации, где он опубликован

Add-Content $OutFile "MATCH (m: Template {name:'$certTemplateName', domain:'$DomainName'}) MATCH (n: CA {objectid:'$ObjectGUID'}) MERGE (m)-[r: HostedOn]->(n);"

# Создаем Cypher-запрос на установку свойства enabled в значение true

Add-Content $OutFile "MATCH (m: Template {name:'$certTemplateName', domain:'$DomainName'}) SET m.enabled = True;"

}

}

}

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

..\Get-ADCSInformation.ps1

Get-ADCSInfo

.\neo4j_uploaddata.ps1

UploadData -file.\ADCS_29032024100810.log


Рис. 4.73. Выполнение скриптов


Проверим, что у нас получилось, и выполним следующий Cypher-запрос в браузере neo4j.

MATCH (n) WHERE n: Template OR n: CA RETURN n

Отображение метки шаблонов сертификатов в BloodHound

Теперь добавим отображение метки шаблонов сертификатов в BloodHound. Все действия будут аналогичны действиям с метками, сделанным ранее.

Переходим в директорию

src
и открываем файл
index.js
на редактирование. Добавим информацию о том, как новая метка будет отображаться на графе. Находим строку
global.AppStore
и вставляем следующий код после блока
Share
:

global.appStore = {

dagre: true,

Share:{

font: "'Font Awesome 5 Free'",

content:'\uf07b',

scale:1.5,

color:'#f8d775',

},

Template:{

font: "'Font Awesome 5 Free'",

content:'\uf2c2',

scale:1.25,

color:'#cc0066',

},

Дальше ищем строку

lowResPalette
и добавляем название метки и цвет. Этот параметр отвечает за отображение узлов в низком разрешении.

lowResPalette:{

colorScheme:{

Base:'#E6E600',

LocalUser:'#E69717',

Share:'#f8d775'
,

Template:'#cc0066',

},

Сохраняем измененный файл.

Теперь переходим в директорию

src\js
и открываем на редактирование файл
utils.js.
В самом начале, в разделе
const labels = [
, добавляем новую метку после
Domain
.

const labels = [

'Domain',

'LocalUser',

'Share',

'Template',

Находим строку

export async function setSchema()
и в массив
label
добавляем название новой метки.

export async function setSchema() {

const luceneIndexProvider = "lucene+native-3.0"

let labels = ["User", "Group", …, "Domain", "Container", "Base", "LocalUser", "Share", 
"Template"

Сохраняем измененный файл.

Теперь нужно добавить метку, чтобы она отображалась на графе. Для этого переходим в директорию

components
и открываем файл
Graph.jsx
. Находим строку
switch (type)
и добавляем в нее код:

switch (type) {

case 'Share':

node.type_share = true;

break;

case 'Template':

node.type_template = true;

break;

}

Сохраняем измененный файл.

Для отображения метки в строке поиска нужно открыть файл

SearchRow.jsx
, который находится в директории
src\components\SearchContainer.
Находим строку
switch
(type)
и после блока
Container
добавляем код:

switch (type) {

case 'Share':

icon.className = 'fa fa-folder';

break;

case 'Template':

icon.className = 'fa fa-id-card';

break;

Сохраняем измененный файл.

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

TabContainer.jsx
и добавляем импорт вкладки:

import LocalUserNodeData from './Tabs/LocalUserNodeData';

import ShareNodeData from './Tabs/ShareNodeData';

import TemplateNodeData from './Tabs/TemplateNodeData';

До нажатия на сам узел его свойства будут скрыты. Для этого в классе

TabContainer
находим строку
this.state
и добавляем строку:

class TabContainer extends Component {

constructor(props) {

super(props);

this.state = {