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

WriteSPN
или
WriteAccountRestriction.

Настройка лаборатории

Прежде чем начать собирать и добавлять информацию, необходимо настроить нашу лабораторию. Для этого открываем ADUC на контроллере домена, во вкладке View включаем Advanced Features и выполняем следующие действия:

● Предоставим права

Write
scriptPath
пользователю
user
над пользователем
victim
.

● Создадим новую OU

Office
.

● Предоставим права

Write gPLink
пользователю
victim
над OU
Office
.

● Создадим объект компьютера

test
.

● Переместим объект компьютера

test
в OU
Office
.

● Предоставим права

Write userAccountControl
пользователю
victim
над компьютером
test
.

● Очистим базу neo4j через BloodHound.

● Заново соберем информацию с помощью SharpHound и загрузим ее в BloodHound.

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

user
до
office
, с помощью BloodHound, то, скорей всего, нам предоставят путь через получение привилегий доменного администратора.

Сбор информации

Для автоматизации процесса сбора информации напишем скрипт (

Get
-
ExtendedACL.ps1
) на
Powershell
, алгоритм которого будет следующим:

● Определим, какие атрибуты нам интересны для сбора.

● Определим класс объектов для ADSI-запроса.

● Для каждого класса объектов получим ACL.

● Выберем права

WriteProperty
.

● Сравним GUID атрибутов с теми, которые нам интересны.

● Сформируем строку запроса Cypher.

Есть два варианта формирования связи: первый – создать связь

WriteProperty
и добавить свойство
property
, в котором будет указано название атрибута; второй – создать связь в виде
Write + Attribute
.

В первом случае придется использовать браузер neo4j, чтобы увидеть, какие свойства можно изменять, во втором в код BloodHound нужно будет добавить все связи. Остановимся на втором варианте.

Список атрибутов, их название и guid можно найти на сайте Microsoft[17].

function GetWriteProperty()

{

# Сопоставление guid с названием атрибута

<#

bf9679a8–0de6–11d0-a285–00aa003049e2 – scriptPath

f30e3bbe-9ff0–11d1-b603–0000f80367c1 – gPLink

bf967a68–0de6–11d0-a285–00aa003049e2 – UserAccountControl

#>

# Создаем файл отчета

[string]$OutFile = "ExtendendACLS_" + $(Get-Date -f

ddMMyyyyhhmmss) +".log"

# Определяем имя домена

$DomainObject = [System.DirectoryServices.

ActiveDirectory.Domain]::GetCurrentDomain()

$DomainName = $DomainObject.name.toUpper()

# Фильтр для классов объектов

$Filters = @(

'(&(objectCategory=person)(objectClass=user))', # Users

'(objectCategory=computer)' # Computers

'(objectCategory=organizationalUnit)' # OU

)

foreach($filter in $filters)

{

# ADSI-запрос с использованием фильтра

$searcher = ([adsisearcher]"$filter")

$searcher.PageSize = 1000

$objects = $searcher.FindAll()

foreach($object in $objects)

{

# Получаем SID или GUID субъекта

if($object.Properties.objectsid)

{

$ID = (New-Object System.Security.Principal.

SecurityIdentifier($object.Properties.objectsid.

Item(0),0)).Value

}

else

{

$ID = [guid]$object.Properties.objectguid[0]|

Select-Object -ExpandProperty Guid

$ID = $ID.ToUpper()

}

# Получаем ACL объекта

$acls = ([ADSI]$object.path).ObjectSecurity.Access

foreach($acl in $acls)

{

# Проверка для атрибута scriptPath

if($acl.ActiveDirectoryRights -match "WriteProperty"-and $acl.ObjectType -match "bf9679a8–0de6–11d0-a285–00aa003049e2")

{

#Получаем SID объекта из его имени

$IdentityReference = new-object System.Security.Principal.NTAccount($acl.IdentityReference)

$ObjectSID = $IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]). toString()

if($ObjectSID.Length -le 12)

{

$ObjectSID = $DomainName +"-" + $ObjectSID

}

# Записываем результат в файл в виде запроса Cypher

Add-Content $OutFile "MATCH

(m {objectid:'$ObjectSID'}) MATCH

(n {objectid:'$ID'}) MERGE (m)-[r: WriteScriptPath]-

>(n) SET r.isacl=TRUE;"

}

# Проверка для атрибута gPLink

if($acl.ActiveDirectoryRights -match "WriteProperty"-and $acl.ObjectType -match "f30e3bbe-9ff0–11d1-b603–0000f80367c1")

{

#Получаем SID объекта из его имени

$IdentityReference = new-object System.Security.

Principal.NTAccount($acl.IdentityReference)

$ObjectSID = $IdentityReference.Translate([System.

Security.Principal.SecurityIdentifier]). toString()

if($ObjectSID.Length -le 12)

{

$ObjectSID = $DomainName +"-" + $ObjectSID

}

# Записываем результат в файл в виде запроса Cypher

Add-Content $OutFile "MATCH

(m {objectid:'$ObjectSID'}) MATCH

(n {objectid:'$ID'}) MERGE (m)-[r: WriteGPLink]->(n)

SET r.isacl=TRUE;"

}

# Проверка для атрибута UserAccountControl

if($acl.ActiveDirectoryRights -match "WriteProperty"

-and $acl.ObjectType -match "bf967a68–0de6–11d0-a285–

00aa003049e2")

{

#Получаем SID объекта из его имени

$IdentityReference = new-object System.Security.

Principal.NTAccount($acl.IdentityReference)

$ObjectSID = $IdentityReference.Translate([System.

Security.Principal.SecurityIdentifier]). toString()

if($ObjectSID.Length -le 12)

{

$ObjectSID = $DomainName +"-" + $ObjectSID

}

# Записываем результат в файл в виде запроса Cypher

Add-Content $OutFile