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 = {
…