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

Настроенные из шаблонов групповые политики записываются в inf-файлы. Эти файлы имеют свою структуру. В этом разделе мы рассмотрим возможность прочитать эти файлы и записать их содержимое в виде связей и свойств узлов.

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

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

Назначение прав пользователя (Rights Assessments)

К правам пользователя относятся права на вход и разрешения. Права входа определяют, кто имеет право на вход на устройство и как они могут войти в систему. Разрешения прав пользователя управляют доступом к ресурсам компьютера и домена, а также могут переопределять разрешения, заданные для определенных объектов.


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

Простой способ прочитать содержимое файлов

gptTmpl.inf
с помощью powershell: рекурсивно найти все inf-файлы в групповых политиках, отфильтровать файлы по наличию
Rights Assessment
, прочитать содержимое файла и записать его в файл (рис. 4.38).

Get-ChildItem -Path \\dc\SYSVOL\domain.local\Policies\ -Recurse -ea SilentlyContinue -Include ('*.inf')| Select-String -Pattern "Privilege Rights"|ForEach-Object {$name = $_.Path; $name; Get-Content $name;""}| Out-File Rights.txt

В PowerView1 есть функция

Get-GptTmp
[15], которая разбирает inf-файл, а результаты формирует в hashtable (рис. 4.39).

..\PowerView.ps1

(Get-GptTmpl -GptTmplPath "\\dc\SYSVOL\domain.local\Policies\{6AC1786C-016F-11D2–945F-00C04fB984F9}\MACHINE\


Рис. 4.38. Результат поиска в групповых политиках


Рис. 4.39. Поиск информации с помощью PowerView


Microsoft\Windows NT\SecEdit\GptTmpl.inf" -OutputObject).PrivilegeRights

Эту информацию можно добавить в BloodHound. В качестве примера возьмем права

SeMachineAccount
:

MATCH(g: GPO) WHERE g.gpcpath CONTAINS "{6AC1786C-016F-11D2–945F-00C04FB984F9}"

MATCH(g)-[: GPLink|Contains*1..]->(c: Computer)

MATCH (n) WHERE n.objectid CONTAINS "S-1–5–11"

MERGE (n)-[r: SeMachineAccount]->(c)

Проверим, что связь создалась корректно, и выполним следующий запрос в Raw Query в BloodHound:

MATCH p=(n)-[r: SeMachineAccount]->(c: Computer) RETURN p


Рис. 4.40. Проверка создания связи


Чтобы автоматизировать этот процесс, создадим скрипт

GetRightsAssessments.ps1
, который будет формировать запросы Cypher с информацией из inf-файла. За основу возьмем функцию
PowerView Get-IniContent
, которая разбирает inf-файл.

Алгоритм скрипта будет следующим:

● Получить все inf-файлы, в которых есть строка

Privilege Rights
.

● С помощью функции

Get-IniContent
разобрать по циклу полученные inf-файлы

● Выбрать интересующие права.

● Разобрать

SID
на отдельные записи.

● Сформировать строку Cypher, установив свойство

isright=TRUE
для связи.

function Get-RigthsAssesment

{

$DomainName = "domain.local"

$DC = "dc"


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

[string]$OutFile = "RigthsAssesment_" + $(Get-Date -f ddMMyyyyhhmmss) +".log"

# Поиск во всех inf-файлах строки Privilege Rights

$GPOs = Get-ChildItem -Path \\$DC\SYSVOL\$DomainName\ Policies\ -Recurse -ea SilentlyContinue -Include ('*. inf')| Select-String -Pattern "Privilege Rights"

foreach($GPO in $GPOs)

{


# Получить права и SID из групповой политики

$Rights = (Get-IniContent -filePath $GPO.Path). PrivilegeRights.PSObject.Properties| select name, value

# Получить guid групповой политики

$guid = $GPO.Path.Split('\')[6].ToUpper()

foreach ($Right in $Rights)

{

# Поиск интересующих прав

if ($Right.name -match "SeEnableDelegationPrivile ge|SeMachineAccountPrivilege|SeRestorePrivilege|SeTcb Privilege|SeBackupPrivilege|SeCreateTokenPrivilege|Se CreateGlobalPrivilege|SeDebugPrivilege|SeImpersonateP rivilege|SeLoadDriverPrivilege|SeTakeOwnershipPrivile ge|SeAssignPrimaryTokenPrivilege|SeRemoteInteractiveL ogonRight|SeInteractiveLogonRight")

{

foreach($sid in $Right.value)

{


# Подготовка переменных для строки запроса

$sid = $sid.Replace('*','')

$relation = $Right.name.Replace('Privilege','')

if($sid.Length -le 12)

{

$sid = $DomainName.ToUpper() +"-" + $sid

}

# Создание строки запроса Cypher

Add-Content $OutFile "MATCH(g: GPO) WHERE g.gpcpath CONTAINS '$guid' MATCH(g)-[: GPLink|Contains*1..]->(c: Computer) MATCH (n) WHERE n.objectid CONTAINS '$sid' MERGE (n)-[r:$relation]->(c) SET r.isright = true;"

}

}

}

}

}

# Get-IniContent из PowerView

function Get-IniContent ($filePath)

{

$IniObject = New-Object PSObject

switch -regex -file $FilePath

{

"^\[(.+)\]" # Section

{

$Section = $matches[1].Trim()

$Section = $Section.Replace('', '')

$SectionObject = New-Object PSObject

$IniObject | Add-Member Noteproperty $Section

$SectionObject

$CommentCount = 0

}

"^(;.*)$" # Comment

{

$value = $matches[1].Trim()

$CommentCount = $CommentCount + 1

$name = "Comment" + $CommentCount

$Name = $Name.Replace('', '')

$IniObject.$Section | Add-Member Noteproperty $Name $Value

}

"(.+?)\s*=(.*)" # Key

{

$Name,$Value = $matches[1..2]

$Name = $Name.Trim()

$Values = $Value.split(',') | ForEach-Object {$_. Trim()}

$Name = $Name.Replace('', '')

$IniObject.$Section | Add-Member Noteproperty $Name $Values

}

}

return $IniObject

}

Как вариант, можно использовать общее название связи, например

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

Тогда запрос Cypher будет иметь следующий вид:

"MATCH(g: GPO) WHERE g.gpcpath CONTAINS '$guid' MATCH(g)-[: GPLink|Contains*1..]->(c: Computer) MATCH (n) WHERE n.objectid CONTAINS '$sid' MERGE (n)-[r: HasPrivilege]->(c) SET r.isright = true SET r.rightname ='$relation'"

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