
Оглавление
1. Введение: почему «видимый» список администраторов — это иллюзия
2. Анатомия скрытой привилегии: как аккаунт становится администратором незаметно
3. Правовые и процедурные основы аудита AD
4. Метод 1 — PowerShell: инвентаризация привилегированных групп и прямых прав
5. Метод 2 — BloodHound: граф скрытых путей к Domain Admin
6. Метод 3 — Анализ Event Log: кто и когда получил права администратора
7. Метод 4 — Анализ SAM и локальных аккаунтов: скрытые учётные записи на хостах
8. Метод 5 — PingCastle и Netwrix: автоматизированная оценка рисков AD
9. Признаки backdoor-аккаунта: паттерны, которые оставляет атакующий
10. SID History: классический механизм скрытой эскалации привилегий
11. AdminSDHolder и ACL-манипуляции: скрытые права через объекты AD
12. Реагирование: что делать при обнаружении backdoor-аккаунта
13. Практический кейс: полный аудит от нуля до отчёта
14. FAQ: 12 горячих вопросов об аудите привилегированных аккаунтов AD
15. Чек-лист: аудит привилегированных аккаунтов AD за один рабочий день
16. Заключение и теги
1. Введение: почему «видимый» список администраторов — это иллюзия
Откройте «Active Directory Users and Computers», перейдите в группу Domain Admins и посмотрите список. Вы видите 5 аккаунтов. Это все администраторы домена?
Нет. BloodHound может обнаружить два аккаунта с правами локального администратора на контроллерах домена, которые не входят в группу Domain Admins и вовсе не отображаются в стандартных запросах. Это и есть «скрытые администраторы».
Скрытая административная привилегия — это любая конфигурация, при которой аккаунт получает права администратора не через прямое членство в очевидных привилегированных группах (Domain Admins, Enterprise Admins), а через:
- Вложенное членство в группах (Account A → Group B → Group C → Domain Admins)
- Прямые права ACL на объекты AD (WriteDACL, GenericAll, ForceChangePassword)
- SID History с привилегированными SID из других доменов
- AdminSDHolder-манипуляции
- Права GPO на создание задач или сервисов
- Локальное администрирование на критичных хостах через вложенные группы
После компрометации домена атакующие почти всегда оставляют backdoor-аккаунты — именно через такие скрытые механизмы. Слабые учётные данные давно забытых административных аккаунтов — одна из наиболее целевых конфигурационных уязвимостей, которую ищет ransomware для масштабирования атаки.
| Тип скрытой привилегии | Обнаруживается стандартным просмотром AD | Обнаруживается BloodHound | Обнаруживается PowerShell аудитом |
|---|---|---|---|
| Прямое членство в Domain Admins | ✅ | ✅ | ✅ |
| Вложенное членство 3+ уровней | ❌ | ✅ | ✅ (Get-ADGroupMember -Recursive) |
| WriteDACL на привилегированный объект | ❌ | ✅ | ⚠️ Сложно вручную |
| SID History с привилегированным SID | ❌ | ✅ | ✅ (Get-ADUser sidHistory) |
| AdminSDHolder наследование | ❌ | ✅ | ⚠️ Требует ACL-анализа |
| Backdoor через GPO | ❌ | ⚠️ Частично | ✅ (GPO-анализ) |
> *💡 Статья написана для Blue Team, системных администраторов и специалистов по безопасности, выполняющих аудит собственной инфраструктуры или IR-расследование после инцидента.*
2. Анатомия скрытой привилегии: как аккаунт становится администратором незаметно
Механизм 1: Вложенное членство в группах
Active Directory поддерживает вложенные группы произвольной глубины. Каждый уровень вложения снижает видимость привилегии.
text
Пример: пользователь user_helpdesk
Видимое: user_helpdesk → группа IT_Helpdesk
Скрытое: IT_Helpdesk → IT_Operations → IT_Infrastructure_Admins
IT_Infrastructure_Admins → Domain Admins
Результат: user_helpdesk является Domain Admin,
но это не видно при просмотре группы Domain Admins
Именно через такие цепочки членства в группах BloodHound показывает, как непривилегированный пользователь может стать Domain Admin через несколько шагов.
Механизм 2: Права ACL на объекты AD
Каждый объект Active Directory (пользователь, группа, OU) имеет список управления доступом (DACL). Права на объект позволяют косвенно получить административный доступ.
text
Опасные права ACL:
GenericAll → Полный контроль над объектом
WriteDACL → Изменение прав на объект (включая себя)
WriteOwner → Смена владельца → WriteAll
GenericWrite → Запись произвольных атрибутов
ForceChangePassword → Сброс пароля без знания текущего
AddMember (на привилегированную группу) → Добавить себя в Domain Admins
Аккаунт, имеющий `AddMember` на группу Domain Admins, не является администратором прямо сейчас — но может стать им в одно действие. Это и есть скрытая привилегия.
Механизм 3: SID History
При миграции между доменами AD сохраняет историю SID пользователя. Если в поле `sIDHistory` аккаунта записан SID из привилегированной группы — при аутентификации Windows добавит этот SID в токен, предоставив соответствующие права.
text
Пример атаки:
Атакующий имеет доступ к контроллеру домена →
Записывает в sIDHistory аккаунта user_backup
значение SID группы Domain Admins →
user_backup получает права Domain Admin при входе,
но не числится в Domain Admins ни в каком интерфейсе
Механизм 4: AdminSDHolder
AdminSDHolder — специальный объект AD, права которого периодически распространяются (через SDProp) на все привилегированные учётные записи. Если атакующий модифицирует ACL AdminSDHolder — он получает персистентный backdoor, который восстанавливается автоматически даже после удаления вручную.
3. Правовые и процедурные основы аудита AD
Аудит Active Directory — это операция с широкими правами в корпоративной инфраструктуре. Даже при наличии технических полномочий важно соблюдать процедурные рамки.
Минимальные права для проведения аудита
Большинство методов из этой статьи не требуют прав Domain Admin. SharpHound может работать с правами обычного пользователя домена и собирать данные о правах, сессиях и членстве в группах.
text
Права, необходимые для разных методов:
Только Domain User:
Get-ADGroupMember (чтение групп)
BloodHound / SharpHound (сбор данных AD)
PingCastle (healthcheck)
Domain Admin (или делегированные права):
Чтение атрибута sIDHistory
Чтение ACL объектов AdminSDHolder
Анализ Security Event Log на DC
Доступ к NTDS.dit / VSS-снимкам
Local Admin на хосте:
Анализ локального SAM
Get-LocalGroupMember на хосте
Необходимые документы
text
Для внутреннего аудита:
✓ Приказ или задание от руководства / CISO
✓ Согласование с владельцем AD / IT-директором
✓ Журнал действий аудитора (что, когда, на чём)
Для IR-расследования:
✓ Приказ о расследовании инцидента
✓ Цепочка хранения доказательств
✓ Фиксация хэшей всех извлечённых файлов
Для внешнего аудита / пентеста:
✓ Договор с явным scope (какие домены, какие системы)
✓ Письмо об авторизации
✓ NDA
Что документировать в процессе
text
Каждое действие в ходе аудита:
- Временна́я метка
- Использованный инструмент / команда
- Система, на которой выполнялась команда
- Результат (скриншот или сохранённый вывод)
4. Метод 1 — PowerShell: инвентаризация привилегированных групп и прямых прав
PowerShell + модуль ActiveDirectory — первый и наиболее доступный инструмент аудита. Не требует установки стороннего ПО.
Установка и базовые запросы
powershell
<h2 id="ustanovit-modul-ad-esli-ne-ustanovlen">Установить модуль AD (если не установлен):</h2>
Install-WindowsFeature -Name RSAT-AD-PowerShell
<h2 id="ili-na-klientskoy-mashine">Или на клиентской машине:</h2>
Add-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0"
<h2 id="proverit-podklyuchenie-k-domenu">Проверить подключение к домену:</h2>
Get-ADDomain | Select-Object Name, DomainMode, PDCEmulator
Инвентаризация привилегированных групп
powershell
<h2 id="perechen-vseh-privilegirovannyh-grupp-domena">Перечень ВСЕХ привилегированных групп домена:</h2>
$PrivilegedGroups = @(
"Domain Admins",
"Enterprise Admins",
"Schema Admins",
"Administrators",
"Account Operators",
"Backup Operators",
"Print Operators",
"Server Operators",
"Group Policy Creator Owners",
"Domain Controllers",
"Read-only Domain Controllers",
"Protected Users"
)
<h2 id="dlya-kazhdoy-gruppy-rekursivnoe-chlenstvo-vklyuchaya-vlozhennye">Для каждой группы — рекурсивное членство (включая вложенные!):</h2>
foreach ($group in $PrivilegedGroups) {
Write-Host "`n=== $group ===" -ForegroundColor Cyan
try {
Get-ADGroupMember -Identity $group -Recursive |
Select-Object Name, SamAccountName, objectClass |
Format-Table -AutoSize
} catch {
Write-Warning "Группа '$group' не найдена или недоступна: $_"
}
}
Поиск аккаунтов с прямыми привилегированными правами (не через группу)
powershell
<h2 id="nayti-polzovateley-s-admincount-1">Найти пользователей с AdminCount = 1</h2>
<h2 id="admincount-1-oznachaet-chto-akkaunt-kogda-libo-byl-v-privilegirovannoy-gruppe">(AdminCount=1 означает, что аккаунт когда-либо был в привилегированной группе</h2>
<h2 id="ili-imeet-zaschischyonnyy-acl-ot-adminsdholder">или имеет защищённый ACL от AdminSDHolder)</h2>
Get-ADUser -Filter {AdminCount -eq 1} -Properties AdminCount, LastLogonDate, PasswordLastSet |
Select-Object Name, SamAccountName, Enabled, LastLogonDate, PasswordLastSet |
Sort-Object LastLogonDate -Descending |
Format-Table -AutoSize
<h2 id="vazhno-esli-admincount-1-u-polzovatelya-kotoryy-ne-sostoit">ВАЖНО: Если AdminCount=1 у пользователя, который НЕ состоит</h2>
<h2 id="ni-v-odnoy-privilegirovannoy-gruppe-eto-anomaliya-trebuyuschaya-rassledovaniya">ни в одной привилегированной группе — это аномалия, требующая расследования.</h2>
<h2 id="eto-mozhet-byt-artefakt-posle-udaleniya-iz-privilegirovannoy-gruppy">Это может быть артефакт после удаления из привилегированной группы</h2>
<h2 id="admincount-ne-sbrasyvaetsya-avtomaticheski-ili-backdoor">(AdminCount не сбрасывается автоматически) или backdoor.</h2>Поиск аккаунтов с SID History
powershell
<h2 id="nayti-akkaunty-s-nepustym-sidhistory">Найти аккаунты с непустым sIDHistory:</h2>
Get-ADUser -Filter * -Properties SIDHistory |
Where-Object { $_.SIDHistory -ne $null -and $_.SIDHistory.Count -gt 0 } |
Select-Object Name, SamAccountName, Enabled,
@{N='SIDHistory'; E={ $_.SIDHistory -join ', ' }} |
Format-Table -AutoSize
<h2 id="proverit-sootvetstvuet-li-sid-iz-istorii-privilegirovannoy-gruppe">Проверить, соответствует ли SID из истории привилегированной группе:</h2>
<h2 id="domain-admins-sid-vsegda-zakanchivaetsya-na-512">Domain Admins SID всегда заканчивается на -512</h2>
<h2 id="enterprise-admins-na-519">Enterprise Admins — на -519</h2>
<h2 id="schema-admins-na-518">Schema Admins — на -518</h2>
$DomainSID = (Get-ADDomain).DomainSID.Value
$PrivilegedSIDs = @(
"$DomainSID-512", # Domain Admins
"$DomainSID-519", # Enterprise Admins
"$DomainSID-518", # Schema Admins
"S-1-5-32-544" # Builtin\Administrators
)
Get-ADUser -Filter * -Properties SIDHistory |
Where-Object { $_.SIDHistory.Count -gt 0 } |
ForEach-Object {
$user = $_
foreach ($sid in $user.SIDHistory) {
if ($PrivilegedSIDs -contains $sid.Value) {
Write-Host "⚠️ BACKDOOR SID: $($user.SamAccountName) имеет SID $($sid.Value) в истории" `
-ForegroundColor Red
}
}
}
Поиск неактивных аккаунтов с привилегиями
powershell
<h2 id="akkaunty-domain-admins-ne-vhodivshie-v-sistemu-bolee-90-dney">Аккаунты Domain Admins, не входившие в систему более 90 дней:</h2>
$CutoffDate = (Get-Date).AddDays(-90)
Get-ADGroupMember -Identity "Domain Admins" -Recursive |
Where-Object { $_.objectClass -eq "user" } |
ForEach-Object {
Get-ADUser -Identity $_.SamAccountName -Properties LastLogonDate, Enabled
} |
Where-Object { $_.LastLogonDate -lt $CutoffDate -or $_.LastLogonDate -eq $null } |
Select-Object Name, SamAccountName, Enabled, LastLogonDate |
Format-Table -AutoSize
<h2 id="zachem-neaktivnye-privilegirovannye-akkaunty-tipichnyy-backdoor">Зачем: неактивные привилегированные аккаунты — типичный backdoor.</h2>
<h2 id="atakuyuschiy-aktiviruet-ih-ili-menyaet-parol-deystvie-nezametnoe">Атакующий активирует их или меняет пароль — действие незаметное</h2>
<h2 id="na-fone-davno-neispolzuemogo-akkaunta">на фоне «давно неиспользуемого» аккаунта.</h2>Поиск сервисных аккаунтов с избыточными правами
powershell
<h2 id="servisnye-akkaunty-po-maske-imeni-s-chlenstvom-v-domain-admins">Сервисные аккаунты (по маске имени) с членством в Domain Admins:</h2>
Get-ADGroupMember -Identity "Domain Admins" -Recursive |
Where-Object { $_.objectClass -eq "user" } |
ForEach-Object {
$user = Get-ADUser -Identity $_.SamAccountName -Properties Description
if ($user.SamAccountName -match "svc|service|srv|task|sql|backup|agent") {
Write-Host "⚠️ Сервисный аккаунт в Domain Admins: $($user.SamAccountName)" `
-ForegroundColor Yellow
Write-Host " Описание: $($user.Description)"
}
}
5. Метод 2 — BloodHound: граф скрытых путей к Domain Admin
BloodHound использует теорию графов для обнаружения скрытых взаимосвязей внутри Active Directory, которые иначе остались бы незамеченными. Инструмент способен за минуты сделать то, на что раньше у пентестеров и аналитиков уходили недели.
Установка BloodHound CE (Community Edition)
BloodHound CE (версия 5.x от SpecterOps) — актуальная версия с Docker-установкой:
bash
<h2 id="docker-compose-ustanovka-bloodhound-ce">Docker Compose установка BloodHound CE:</h2>
curl -L https://ghcr.io/specterops/bloodhound/bloodhound-ce \
-o docker-compose.yml
docker compose -f docker-compose.yml up -d
<h2 id="veb-interfeys-http-localhost-8080">Веб-интерфейс: http://localhost:8080</h2>
<h2 id="login-po-umolchaniyu-admin-parol-iz-pervogo-zapuska-loga">Логин по умолчанию: admin / (пароль из первого запуска лога)</h2>
docker compose logs | grep "Initial Password"
Или классический BloodHound (версия 4.x) с Neo4j:
bash
<h2 id="na-ubuntu">На Ubuntu:</h2>
apt install neo4j bloodhound
<h2 id="zapustit-neo4j">Запустить Neo4j:</h2>
neo4j start
<h2 id="otkryt-http-localhost-7474-izmenit-parol">Открыть http://localhost:7474 → изменить пароль</h2>
<h2 id="zapustit-bloodhound">Запустить BloodHound:</h2>
bloodhound &
Сбор данных через SharpHound (на хосте домена)
Запускать SharpHound от привилегированного токена: UAC создаёт фильтрованный токен для администраторов, скрывающий чувствительные привилегии. Из непривилегированной оболочки высокоценные привилегии будут невидимы и BloodHound не проиндексирует соответствующие рёбра.
powershell
<h2 id="skachat-sharphound-s-github-ili-ispolzovat-iz-ustanovki-bloodhound">Скачать SharpHound с GitHub (или использовать из установки BloodHound)</h2>
<h2 id="github-com-bloodhoundad-sharphound-releases">github.com/BloodHoundAD/SharpHound/releases</h2>
<h2 id="bazovyy-sbor-ot-domena-uchastnika-dostatochno-obychnogo-polzovatelya">Базовый сбор — от домена-участника (достаточно обычного пользователя):</h2>
.\SharpHound.exe --CollectionMethods Default --OutputDirectory C:\AuditData\
<h2 id="polnyy-sbor-bolee-shumnyy-no-polnyy">Полный сбор (более шумный, но полный):</h2>
.\SharpHound.exe --CollectionMethods All --OutputDirectory C:\AuditData\
<h2 id="tolko-acl-i-chlenstvo-v-gruppah-tihiy-rezhim">Только ACL и членство в группах (тихий режим):</h2>
.\SharpHound.exe --CollectionMethods Group,ACL --OutputDirectory C:\AuditData\
<h2 id="rezultat-zip-arhiv-s-json-faylami-zagruzit-v-bloodhound">Результат: ZIP-архив с JSON-файлами → загрузить в BloodHound</h2>powershell
<h2 id="powershell-variant-invoke-bloodhound">PowerShell-вариант (Invoke-BloodHound):</h2>
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethods All -OutputDirectory C:\AuditData\
Ключевые запросы для обнаружения скрытых администраторов
После загрузки данных в BloodHound используйте предустановленные запросы:
cypher
/* Все кратчайшие пути к Domain Admins */
MATCH p=shortestPath(
(n:User)-[*1..]->(g:Group {name: "DOMAIN ADMINS@CORP.LOCAL"})
)
RETURN p
/* Найти аккаунты с прямыми правами на группу Domain Admins */
MATCH (n)-[:AddMember|WriteDACL|GenericAll|GenericWrite|WriteOwner]->(g:Group)
WHERE g.name STARTS WITH "DOMAIN ADMINS"
RETURN n.name, g.name
/* Найти все аккаунты с AdminCount=1 */
MATCH (u:User {admincount: true})
RETURN u.name, u.enabled
ORDER BY u.name
/* Найти пользователей с SID History */
MATCH (u:User)
WHERE u.sidhistory IS NOT NULL AND u.sidhistory <> []
RETURN u.name, u.sidhistory
/* Найти аккаунты с производными правами локального администратора на DC */
MATCH (u:User),(c:Computer {name:"DC01.CORP.LOCAL"})
MATCH p=shortestPath((u)-[*1..]->(c))
WHERE NOT u.name STARTS WITH "DOMAIN ADMINS"
RETURN u.name, length(p) AS path_length
ORDER BY path_length
LIMIT 20
Интерпретация результатов: что искать в первую очередь
text
Критические находки (немедленное расследование):
✦ Пользователи с прямым path к Domain Admins через 1–2 шага
✦ Аккаунты с GenericAll на Domain Admins (могут добавить себя)
✦ Аккаунты с WriteDACL на Domain Admins (могут дать себе права)
✦ Аккаунты с SIDHistory → Domain Admins SID
✦ Принципалы с DCSync-правами (GetChanges + GetChangesAll на домен)
Высокий приоритет:
✦ Сервисные аккаунты с путями к Domain Admins
✦ Компьютеры с производными правами локального администратора на DC
✦ Большое количество пользователей в Tier-0 (более 5 — обычно признак небрежности)
Умеренный приоритет:
✦ Аккаунты с ForceChangePassword на привилегированных пользователей
✦ Давно не использованные аккаунты с путями к DA
При анализе Domain Controller в BloodHound можно увидеть аккаунты, имеющие доступ локального администратора к контроллерам домена, которые не входят в Domain Admins и вообще не отображаются в стандартных запросах.
6. Метод 3 — Анализ Event Log: кто и когда получил права администратора
Event Log на контроллерах домена — хронологическая запись всех изменений привилегий. Правильно настроенный аудит позволяет восстановить, когда именно аккаунт получил скрытые права.
Ключевые Event IDs для аудита привилегий
text
Изменения членства в группах:
4728 — Пользователь добавлен в глобальную группу безопасности
4729 — Пользователь удалён из глобальной группы
4732 — Пользователь добавлен в локальную группу безопасности
4733 — Пользователь удалён из локальной группы
4756 — Пользователь добавлен в универсальную группу
4757 — Пользователь удалён из универсальной группы
Изменения аккаунтов:
4720 — Создан новый аккаунт пользователя
4722 — Аккаунт активирован
4725 — Аккаунт деактивирован
4738 — Аккаунт пользователя изменён
4781 — Аккаунт переименован
Изменения прав:
4670 — Изменены права на объект (ACL изменён)
4704 — Назначены права пользователю (UserRights)
4705 — Права пользователя отозваны
Аутентификация привилегированных аккаунтов:
4624 — Успешный вход (LogonType 3 = сетевой)
4672 — Вход с специальными привилегиями (включая DA)
PowerShell-запросы к Event Log
powershell
<h2 id="vse-dobavleniya-v-domain-admins-za-poslednie-30-dney">Все добавления в Domain Admins за последние 30 дней:</h2>
$StartTime = (Get-Date).AddDays(-30)
Get-WinEvent -ComputerName $DCName -FilterHashtable @{
LogName = 'Security'
Id = 4728 # Добавление в глобальную группу
StartTime = $StartTime
} | ForEach-Object {
$xml = [xml]$_.ToXml()
$subjectUser = $xml.Event.EventData.Data |
Where-Object Name -eq 'SubjectUserName' | Select-Object -ExpandProperty '#text'
$targetUser = $xml.Event.EventData.Data |
Where-Object Name -eq 'MemberName' | Select-Object -ExpandProperty '#text'
$targetGroup = $xml.Event.EventData.Data |
Where-Object Name -eq 'TargetUserName' | Select-Object -ExpandProperty '#text'
# Фильтровать только добавления в привилегированные группы:
if ($targetGroup -match "Domain Admins|Enterprise Admins|Schema Admins|Administrators") {
[PSCustomObject]@{
Time = $_.TimeCreated
Action = "ДОБАВЛЕН в $targetGroup"
Subject = $subjectUser # Кто добавил
Target = $targetUser # Кого добавили
}
}
} | Sort-Object Time | Format-Table -AutoSize
powershell
<h2 id="sozdanie-novyh-akkauntov-za-poslednie-7-dney-potentsialnye-backdoor">Создание новых аккаунтов за последние 7 дней (потенциальные backdoor):</h2>
Get-WinEvent -ComputerName $DCName -FilterHashtable @{
LogName = 'Security'
Id = 4720
StartTime = (Get-Date).AddDays(-7)
} | ForEach-Object {
$xml = [xml]$_.ToXml()
[PSCustomObject]@{
Time = $_.TimeCreated
NewAccount = ($xml.Event.EventData.Data | Where-Object Name -eq 'TargetUserName').'#text'
CreatedBy = ($xml.Event.EventData.Data | Where-Object Name -eq 'SubjectUserName').'#text'
}
} | Format-Table -AutoSize
powershell
<h2 id="vhod-s-povyshennymi-privilegiyami-event-4672">Вход с повышенными привилегиями (Event 4672):</h2>
<h2 id="esli-obychnyy-akkaunt-poluchil-token-s-privilegiyami-da-eto-anomaliya">Если обычный аккаунт получил токен с привилегиями DA — это аномалия</h2>
Get-WinEvent -ComputerName $DCName -FilterHashtable @{
LogName = 'Security'
Id = 4672
StartTime = (Get-Date).AddDays(-1)
} | ForEach-Object {
$xml = [xml]$_.ToXml()
$user = ($xml.Event.EventData.Data | Where-Object Name -eq 'SubjectUserName').'#text'
$privs = ($xml.Event.EventData.Data | Where-Object Name -eq 'PrivilegeList').'#text'
[PSCustomObject]@{
Time = $_.TimeCreated
User = $user
Privs = $privs -replace "`n", "; "
}
} | Where-Object { $_.User -ne "SYSTEM" -and $_.User -ne "-" } |
Format-Table -AutoSize
Настройка аудита для максимальной видимости
powershell
<h2 id="vklyuchit-neobhodimye-kategorii-audita-na-dc">Включить необходимые категории аудита на DC:</h2>
<h2 id="vypolnyat-ot-domain-admin-na-dc">(Выполнять от Domain Admin на DC)</h2>
<h2 id="audit-upravleniya-uchyotnymi-zapisyami">Аудит управления учётными записями:</h2>
auditpol /set /subcategory:"User Account Management" /success:enable /failure:enable
auditpol /set /subcategory:"Security Group Management" /success:enable /failure:enable
auditpol /set /subcategory:"Distribution Group Management" /success:enable
<h2 id="audit-izmeneniy-politiki">Аудит изменений политики:</h2>
auditpol /set /subcategory:"Authorization Policy Change" /success:enable
<h2 id="audit-vhodov">Аудит входов:</h2>
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Special Logon" /success:enable
<h2 id="audit-izmeneniy-obektov-dlya-acl-izmeneniy">Аудит изменений объектов (для ACL-изменений):</h2>
auditpol /set /subcategory:"Directory Service Changes" /success:enable
<h2 id="proverit-tekuschie-nastroyki">Проверить текущие настройки:</h2>
auditpol /get /category:*
Централизованный сбор Event Log
powershell
<h2 id="windows-event-collector-nastroit-peresylku-event-log-s-dc-na-siem">Windows Event Collector: настроить пересылку Event Log с DC на SIEM</h2>
<h2 id="na-dc-dobavit-siem-v-gruppu-event-log-readers">На DC добавить SIEM в группу Event Log Readers:</h2>
Add-ADGroupMember -Identity "Event Log Readers" -Members "SIEM_Service_Account"
<h2 id="ili-nastroit-wef-windows-event-forwarding-cherez-gpo">Или настроить WEF (Windows Event Forwarding) через GPO:</h2>
<h2 id="computer-configuration-windows-settings-security-settings">Computer Configuration → Windows Settings → Security Settings</h2>
<h2 id="event-log-subscription-manager">→ Event Log → Subscription Manager</h2>7. Метод 4 — Анализ SAM и локальных аккаунтов: скрытые учётные записи на хостах
SAM (Security Account Manager) — база данных локальных учётных записей Windows на каждом хосте. Критичные хосты (DC, серверы приложений, файловые серверы) могут иметь скрытые локальные аккаунты с административными правами.
Почему локальные SAM-аккаунты важны для аудита AD
Даже при наличии строгого аудита AD локальные аккаунты на членах домена — слабое место. После компрометации атакующий может:
- Создать локальный администратор на критичном хосте
- Использовать одинаковый пароль локального администратора на всех хостах (Pass-the-Hash lateral movement)
- Использовать LAPS-уязвимость для доступа к паролям LAPS
Инвентаризация локальных администраторов через PowerShell
powershell
<h2 id="na-odnom-hoste-spisok-chlenov-lokalnoy-gruppy-administrators">На одном хосте — список членов локальной группы Administrators:</h2>
Get-LocalGroupMember -Group "Administrators" |
Select-Object Name, PrincipalSource, ObjectClass |
Format-Table -AutoSize
<h2 id="udalyonno-na-neskolkih-hostah-trebuet-winrm-ili-admin-share">Удалённо на нескольких хостах (требует WinRM или admin-share):</h2>
$Servers = Get-ADComputer -Filter {OperatingSystem -like "*Server*"} |
Select-Object -ExpandProperty Name
$Results = foreach ($Server in $Servers) {
try {
$Members = Invoke-Command -ComputerName $Server -ScriptBlock {
Get-LocalGroupMember -Group "Administrators"
} -ErrorAction Stop
$Members | Select-Object @{N='Server';E={$Server}},
Name, PrincipalSource, ObjectClass
} catch {
Write-Warning "Недоступен: $Server"
}
}
<h2 id="nayti-nestandartnye-lokalnye-akkaunty-administratory">Найти нестандартные локальные аккаунты-администраторы:</h2>
$Results | Where-Object {
$_.PrincipalSource -eq "Local" -and
$_.Name -notmatch "Administrator|SYSTEM"
} | Format-Table -AutoSize
Инвентаризация локальных пользователей на хосте
powershell
<h2 id="vse-lokalnye-polzovateli-ne-tolko-administratory">Все локальные пользователи (не только администраторы):</h2>
Get-LocalUser | Select-Object Name, Enabled, LastLogon, PasswordLastSet,
PasswordNeverExpires, Description |
Format-Table -AutoSize
<h2 id="priznaki-backdoor-akkaunta">Признаки backdoor-аккаунта:</h2>
<h2 id="imya-ne-sovpadayuschee-s-korporativnym-standartom-imenovaniya">- Имя, не совпадающее с корпоративным стандартом именования</h2>
<h2 id="passwordneverexpires-true-u-nestandartnogo-akkaunta">- PasswordNeverExpires = True у нестандартного аккаунта</h2>
<h2 id="lastlogon-nedavno-no-accountcreated-davno-i-nezametno">- LastLogon недавно, но AccountCreated — давно и незаметно</h2>
<h2 id="opisanie-pustoe-ili-nestandartnoe">- Описание пустое или нестандартное</h2>О дампе SAM-хэшей: что это такое и почему это не нужно для аудита
SAM-хэши — это NTLM-хэши паролей локальных пользователей, хранящиеся в зашифрованном виде в реестре Windows (`HKLM\SAM`). Дамп хэшей — техника из арсенала атакующих (Mimikatz `lsadump::sam`), применяемая для получения паролей в ходе атаки.
Для задач аудита дамп SAM не нужен: инвентаризация учётных записей через `Get-LocalUser` и `Get-LocalGroupMember` даёт всю необходимую информацию — без извлечения учётных данных.
Дамп SAM/NTDS.dit применяется в IR-расследовании в двух случаях: определение факта кражи хэшей (для уведомления об инциденте) и верификация слабых паролей через crack в контролируемой среде (только при явном разрешении и в рамках пентеста).
Обнаружение признаков дампа SAM (для защиты)
powershell
<h2 id="poisk-v-event-log-priznakov-dampa-sam-event-4656-objectname-sam">Поиск в Event Log признаков дампа SAM (Event 4656 + ObjectName=SAM):</h2>
Get-WinEvent -FilterHashtable @{
LogName = 'Security'; Id = 4656
StartTime = (Get-Date).AddDays(-7)
} | ForEach-Object {
$xml = [xml]$_.ToXml()
$obj = ($xml.Event.EventData.Data | Where-Object Name -eq 'ObjectName').'#text'
if ($obj -match 'SAM\\SAM|\\samr') {
Write-Host "⚠️ Доступ к SAM: $($_.TimeCreated) — $obj" -ForegroundColor Red
}
}
<h2 id="poisk-ispolzovaniya-volume-shadow-copy-dlya-obhoda-sam-blokirovki">Поиск использования Volume Shadow Copy для обхода SAM-блокировки:</h2>
Get-WinEvent -FilterHashtable @{
LogName = 'Security'; Id = 4688
StartTime = (Get-Date).AddDays(-7)
} | Where-Object {
$_.Message -match "vssadmin|HarddiskVolumeShadow|ntdsutil"
}
8. Метод 5 — PingCastle и Netwrix: автоматизированная оценка рисков AD
PingCastle — бесплатный инструмент для автоматизированной оценки безопасности AD с риск-скором и отчётом в HTML-формате.
PingCastle: быстрый healthcheck
powershell
<h2 id="skachat-s-pingcastle-com-download-html-besplatnaya-versiya">Скачать с pingcastle.com/download.html (бесплатная версия)</h2>
<h2 id="bazovyy-healthcheck-domena">Базовый healthcheck домена:</h2>
.\PingCastle.exe --healthcheck --server corp.local
<h2 id="polnyy-sbor-dannyh">Полный сбор данных:</h2>
.\PingCastle.exe --healthcheck --level Full --server corp.local --user audit_user
<h2 id="rezultat-html-otchyot-s">Результат: HTML-отчёт с:</h2>
<h2 id="risk-skorom-0-100-menshe-luchshe">- Риск-скором (0–100, меньше = лучше)</h2>
<h2 id="razbivkoy-po-kategoriyam-privilegirovannye-akkaunty">- Разбивкой по категориям: привилегированные аккаунты,</h2>
<h2 id="ustarevshie-nastroyki-acl-riski-kerberos-konfiguratsiya">устаревшие настройки, ACL-риски, Kerberos-конфигурация</h2>
<h2 id="konkretnymi-rekomendatsiyami-po-kazhdoy-nahodke">- Конкретными рекомендациями по каждой находке</h2>PingCastle проверяет в том числе:
- Аккаунты с AdminCount=1, не состоящие в привилегированных группах
- SID History с привилегированными значениями
- Аккаунты Domain Admins с устаревшими паролями
- Неограниченное делегирование (Unconstrained Delegation)
- AS-REP Roastable аккаунты
Netwrix Auditor / Netwrix Account Lockout Examiner
Netwrix предоставляет AD-анализ включая обнаружение злоупотребления ACL, поиск неиспользуемых привилегированных аккаунтов и мониторинг изменений в привилегированных группах.
powershell
<h2 id="netwrix-change-reporter-besplatnaya-versiya">Netwrix Change Reporter (бесплатная версия):</h2>
<h2 id="otslezhivaet-izmeneniya-v-ad-v-realnom-vremeni">Отслеживает изменения в AD в реальном времени</h2>
<h2 id="otpravlyaet-alerty-pri-izmenenii-privilegirovannyh-grupp">Отправляет алерты при изменении привилегированных групп</h2>
<h2 id="nastroyka-alerta-cherez-powershell-skript-monitoringa">Настройка алерта через PowerShell-скрипт мониторинга:</h2>
<h2 id="zapuskat-kak-scheduled-task-kazhdyy-chas">(Запускать как scheduled task каждый час)</h2>
$PrivGroups = @("Domain Admins","Enterprise Admins","Schema Admins")
$StateFile = "C:\Audit\da_members_baseline.xml"
$CurrentState = foreach ($g in $PrivGroups) {
Get-ADGroupMember -Identity $g -Recursive |
Where-Object objectClass -eq "user" |
Select-Object SamAccountName, @{N='Group';E={$g}}
}
if (Test-Path $StateFile) {
$Baseline = Import-Clixml $StateFile
$Added = Compare-Object $Baseline $CurrentState -Property SamAccountName, Group |
Where-Object SideIndicator -eq "=>"
$Removed = Compare-Object $Baseline $CurrentState -Property SamAccountName, Group |
Where-Object SideIndicator -eq "<="
if ($Added) {
Send-MailMessage -To "security@corp.local" -From "monitor@corp.local" `
-Subject "⚠️ АЛЕРТ: Добавлен аккаунт в привилегированную группу" `
-Body "Добавлены: $($Added.SamAccountName -join ', ')" `
-SmtpServer "smtp.corp.local"
}
}
$CurrentState | Export-Clixml $StateFile
9. Признаки backdoor-аккаунта: паттерны, которые оставляет атакующий
После компрометации домена атакующий создаёт persistence. Зная типичные паттерны, можно выявить backdoor.
Паттерн 1: Аккаунт создан в нерабочее время
powershell
<h2 id="poisk-akkauntov-sozdannyh-nochyu-ili-v-vyhodnye">Поиск аккаунтов, созданных ночью или в выходные:</h2>
Get-ADUser -Filter * -Properties WhenCreated |
Where-Object {
$h = $_.WhenCreated.Hour
$d = $_.WhenCreated.DayOfWeek
# Ночное время или выходные:
($h -lt 7 -or $h -gt 20) -or
($d -eq "Saturday" -or $d -eq "Sunday")
} |
Select-Object Name, SamAccountName, WhenCreated, Enabled |
Sort-Object WhenCreated -Descending |
Format-Table -AutoSize
Паттерн 2: Несоответствие имени корпоративному стандарту
powershell
<h2 id="primer-v-kompanii-prinyat-standart-imyon-firstname-lastname">Пример: в компании принят стандарт имён "firstname.lastname"</h2>
<h2 id="nayti-akkaunty-ne-sootvetstvuyuschie-standartu">Найти аккаунты, не соответствующие стандарту:</h2>
$NamingPattern = "^[a-z]+\.[a-z]+$" # Примерный шаблон
Get-ADUser -Filter * |
Where-Object {
$_.SamAccountName -notmatch $NamingPattern -and
$_.SamAccountName -notmatch "^(Administrator|Guest|krbtgt|DefaultAccount)$"
} |
Select-Object Name, SamAccountName, Enabled, WhenCreated |
Format-Table -AutoSize
Паттерн 3: Аккаунт с AdminCount=1 и недавним WhenChanged
powershell
<h2 id="akkaunty-s-admincount-1-izmenyonnye-nedavno-potentsialnyy-backdoor">Аккаунты с AdminCount=1, изменённые недавно (потенциальный backdoor):</h2>
Get-ADUser -Filter {AdminCount -eq 1} -Properties AdminCount, WhenChanged, WhenCreated |
Where-Object { $_.WhenChanged -gt (Get-Date).AddDays(-30) } |
Select-Object SamAccountName, Enabled, WhenCreated, WhenChanged |
Sort-Object WhenChanged -Descending |
Format-Table -AutoSize
Паттерн 4: Аккаунт с «фиктивным» описанием
powershell
<h2 id="akkaunty-s-opisaniem-imitiruyuschim-sistemnyy-akkaunt">Аккаунты с описанием, имитирующим системный аккаунт:</h2>
Get-ADUser -Filter * -Properties Description |
Where-Object {
$_.Description -match "system|service|built-in|windows|default" -and
$_.SamAccountName -notmatch "^(SYSTEM|krbtgt|Administrator|Guest)$"
} |
Select-Object SamAccountName, Description, Enabled, WhenCreated |
Format-Table -AutoSize
Паттерн 5: Аккаунт с нетипичным атрибутом userAccountControl
powershell
<h2 id="privilegirovannye-akkaunty-bez-ogranicheniy-parolya">Привилегированные аккаунты без ограничений пароля:</h2>
$DAMembers = Get-ADGroupMember "Domain Admins" -Recursive |
Where-Object objectClass -eq "user"
foreach ($member in $DAMembers) {
$user = Get-ADUser $member.SamAccountName -Properties PasswordNeverExpires,
DoesNotRequirePreAuth, TrustedForDelegation
if ($user.PasswordNeverExpires) {
Write-Host "⚠️ DA без срока действия пароля: $($user.SamAccountName)" -ForegroundColor Red
}
if ($user.DoesNotRequirePreAuth) {
Write-Host "⚠️ AS-REP Roastable DA: $($user.SamAccountName)" -ForegroundColor Red
}
if ($user.TrustedForDelegation) {
Write-Host "⚠️ DA с Unconstrained Delegation: $($user.SamAccountName)" -ForegroundColor Red
}
}
10. SID History: классический механизм скрытой эскалации привилегий
SID History — атрибут объекта AD, изначально предназначенный для миграции между доменами. Атакующие злоупотребляют им для создания невидимой привилегии.
Как работает SID History атака
text
Нормальное использование (легитимное):
При миграции пользователя из Domain A в Domain B
его старый SID сохраняется в sIDHistory
→ Ресурсы в Domain A остаются доступными
Злоупотребление (атака):
1. Атакующий получает DA в домене
2. Создаёт или изменяет аккаунт user_backdoor
3. Добавляет в sIDHistory значение SID группы
Domain Admins текущего домена
4. user_backdoor при аутентификации получает токен
с SID Domain Admins
5. → Фактически является Domain Admin
6. → НЕ отображается в группе Domain Admins
7. → Сохраняется даже после очистки группы DA
Обнаружение и очистка SID History
powershell
<h2 id="polnyy-audit-sid-history">Полный аудит SID History:</h2>
$DomainSID = (Get-ADDomain).DomainSID.Value
<h2 id="izvestnye-privilegirovannye-sid">Известные привилегированные SID:</h2>
$SensitiveSIDSuffixes = @(
"-500", # Domain Administrator
"-502", # krbtgt
"-512", # Domain Admins
"-516", # Domain Controllers
"-518", # Schema Admins
"-519", # Enterprise Admins
"-520" # Group Policy Creator Owners
)
$Report = Get-ADUser -Filter * -Properties SIDHistory, Enabled, LastLogonDate |
Where-Object { $_.SIDHistory.Count -gt 0 } |
ForEach-Object {
$user = $_
foreach ($sid in $user.SIDHistory) {
$suffix = "-" + $sid.Value.Split("-")[-1]
$isSensitive = $SensitiveSIDSuffixes -contains $suffix
[PSCustomObject]@{
User = $user.SamAccountName
Enabled = $user.Enabled
SIDHistory = $sid.Value
IsSensitive = $isSensitive
LastLogon = $user.LastLogonDate
}
}
}
$Report | Sort-Object IsSensitive -Descending | Format-Table -AutoSize
<h2 id="ochistit-sid-history-ostorozhno-trebuet-da-i-podtverzhdeniya">Очистить SID History (ОСТОРОЖНО: требует DA и подтверждения):</h2>
<h2 id="snachala-sozdat-rezervnuyu-kopiyu">Сначала создать резервную копию!</h2>
<h2 id="set-aduser-identity-user-backdoor-remove-sidhistory-s-1-5-21-xxx-512">Set-ADUser -Identity "user_backdoor" -Remove @{SIDHistory="S-1-5-21-xxx-512"}</h2>Мониторинг изменений SID History
powershell
<h2 id="vklyuchit-audit-izmeneniy-sid-history-cherez-gpo">Включить аудит изменений SID History (через GPO):</h2>
<h2 id="computer-configuration-policies-windows-settings">Computer Configuration → Policies → Windows Settings →</h2>
<h2 id="security-settings-advanced-audit-policy-configuration">Security Settings → Advanced Audit Policy Configuration →</h2>
<h2 id="account-management-audit-user-account-management-success-failure">Account Management → Audit User Account Management → Success/Failure</h2>
<h2 id="sobytie-izmeneniya-sidhistory-budet-zapisano-kak-event-4738">Событие изменения sIDHistory будет записано как Event 4738</h2>
<h2 id="s-upominaniem-atributa-sid-history">с упоминанием атрибута 'SID History'</h2>11. AdminSDHolder и ACL-манипуляции: скрытые права через объекты AD
Что такое AdminSDHolder
AdminSDHolder — объект AD в контейнере `CN=AdminSDHolder,CN=System,DC=corp,DC=local`. Каждые 60 минут (SDProp) Windows копирует его ACL на все аккаунты и группы в привилегированных группах.
Если атакующий получил DA и добавил себя в ACL AdminSDHolder — этот backdoor восстанавливается каждый час автоматически, даже если его удалить вручную.
Аудит ACL AdminSDHolder
powershell
<h2 id="poluchit-i-proverit-acl-adminsdholder">Получить и проверить ACL AdminSDHolder:</h2>
$AdminSDHolder = Get-ADObject "CN=AdminSDHolder,CN=System,$((Get-ADDomain).DistinguishedName)" `
-Properties nTSecurityDescriptor
$ACL = $AdminSDHolder.nTSecurityDescriptor
<h2 id="vyvesti-vse-ace-access-control-entries">Вывести все ACE (Access Control Entries):</h2>
$ACL.Access | Select-Object IdentityReference, ActiveDirectoryRights,
AccessControlType, IsInherited |
Where-Object { $_.AccessControlType -eq "Allow" -and -not $_.IsInherited } |
Sort-Object ActiveDirectoryRights -Descending |
Format-Table -AutoSize
<h2 id="iskat-nestandartnye-zapisi">Искать нестандартные записи:</h2>
<h2 id="standartnye-system-enterprise-admins-domain-admins-administrators">Стандартные: SYSTEM, Enterprise Admins, Domain Admins, Administrators</h2>
<h2 id="nestandartnye-podozritelnye-lyubye-drugie-printsipaly-s-shirokimi-pravami">Нестандартные (подозрительные): любые другие принципалы с широкими правами</h2>Поиск прямых опасных ACL на привилегированных объектах
powershell
<h2 id="funktsiya-analiza-acl-na-obekte-ad">Функция анализа ACL на объекте AD:</h2>
function Get-DangerousACL {
param([string]$ObjectDN)
$DangerousRights = @(
"GenericAll", "GenericWrite", "WriteDacl", "WriteOwner",
"WriteProperty", "ExtendedRight"
)
$obj = Get-ADObject -Identity $ObjectDN -Properties nTSecurityDescriptor
$obj.nTSecurityDescriptor.Access |
Where-Object {
$_.AccessControlType -eq "Allow" -and
-not $_.IsInherited -and
($DangerousRights | Where-Object { $_.ActiveDirectoryRights -match $_ })
} |
Select-Object IdentityReference, ActiveDirectoryRights, ObjectType
}
<h2 id="proverit-acl-na-klyuchevyh-obektah">Проверить ACL на ключевых объектах:</h2>
$DomainDN = (Get-ADDomain).DistinguishedName
<h2 id="acl-na-obekte-domena-dcsync-prava">ACL на объекте домена (DCSync-права):</h2>
Get-DangerousACL -ObjectDN $DomainDN
<h2 id="acl-na-adminsdholder">ACL на AdminSDHolder:</h2>
Get-DangerousACL -ObjectDN "CN=AdminSDHolder,CN=System,$DomainDN"
<h2 id="acl-na-gruppe-domain-admins">ACL на группе Domain Admins:</h2>
$DAGroup = Get-ADGroup "Domain Admins" -Properties DistinguishedName
Get-DangerousACL -ObjectDN $DAGroup.DistinguishedName
Признаки DCSync-backdoor
DCSync — техника, позволяющая аккаунту с правами `GetChanges` + `GetChangesAll` реплицировать хэши паролей с DC, не имея физического доступа к нему.
powershell
<h2 id="nayti-akkaunty-s-dcsync-pravami-ne-domain-admins">Найти аккаунты с DCSync-правами (не Domain Admins):</h2>
$DomainDN = (Get-ADDomain).DistinguishedName
<h2 id="prava-replikatsii-getchanges-1131f6aa-i-getchangesall-1131f6ad">Права репликации: GetChanges (1131f6aa-...) и GetChangesAll (1131f6ad-...)</h2>
$GetChangesGUID = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"
$GetChangesAllGUID = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"
$DomainACL = (Get-ADObject $DomainDN -Properties nTSecurityDescriptor).nTSecurityDescriptor
$DCSync = $DomainACL.Access | Where-Object {
$_.ObjectType -in @($GetChangesGUID, $GetChangesAllGUID) -and
$_.AccessControlType -eq "Allow"
} | Select-Object IdentityReference, ObjectType
<h2 id="vse-printsipaly-s-dcsync-pravami">Все принципалы с DCSync-правами:</h2>
$DCSync | Group-Object IdentityReference |
Where-Object {
# Фильтр: исключить стандартные (SYSTEM, DA, EA, DC-группа):
$_.Name -notmatch "Domain Admins|Enterprise Admins|Domain Controllers|SYSTEM|Administrator"
} |
ForEach-Object {
Write-Host "⚠️ DCSync backdoor: $($_.Name)" -ForegroundColor Red
}
12. Реагирование: что делать при обнаружении backdoor-аккаунта
Алгоритм реагирования
text
Шаг 1: Документирование (ДО любых действий)
→ Экспортировать все атрибуты аккаунта в файл
→ Сохранить Event Log за период существования аккаунта
→ Зафиксировать хэши артефактов (MD5/SHA256)
Шаг 2: Оценка масштаба
→ Сколько аккаунтов скомпрометировано?
→ Есть ли другие backdoor-механизмы (SID History, AdminSDHolder)?
→ Когда произошла первоначальная компрометация?
→ Какие данные могли быть доступны?
Шаг 3: Сдерживание (Containment)
→ Деактивировать backdoor-аккаунт (не удалять сразу!)
→ Сбросить пароль krbtgt (дважды, с интервалом 10 часов)
→ Сбросить пароли всех реальных Domain Admins
→ Изолировать скомпрометированные хосты
Шаг 4: Устранение
→ Удалить backdoor-аккаунт
→ Очистить SID History
→ Восстановить ACL AdminSDHolder из чистого состояния
→ Удалить DCSync-права с нестандартных аккаунтов
→ Пересмотреть все ACL привилегированных объектов
Шаг 5: Восстановление и усиление
→ Внедрить мониторинг (алерты на изменения DA-группы)
→ Настроить Privileged Access Workstations (PAW)
→ Ввести обязательный MFA для привилегированных аккаунтов
→ Ограничить количество DA (не более 3–5)
Сброс krbtgt: обязательный шаг при компрометации DA
powershell
<h2 id="vazhno-sbrasyvat-krbtgt-nuzhno-dvazhdy-s-intervalom-10-chasov">ВАЖНО: сбрасывать krbtgt нужно ДВАЖДЫ с интервалом ≥ 10 часов</h2>
<h2 id="srok-deystviya-kerberos-tiketa">(срок действия Kerberos-тикета)</h2>
<h2 id="poluchit-tekuschee-sostoyanie-krbtgt">Получить текущее состояние krbtgt:</h2>
Get-ADUser -Identity krbtgt -Properties PasswordLastSet, PasswordNeverExpires
<h2 id="shag-1-pervyy-sbros-parolya">Шаг 1: Первый сброс пароля:</h2>
$NewPwd = [System.Web.Security.Membership]::GeneratePassword(64, 8)
Set-ADAccountPassword -Identity krbtgt -NewPassword (ConvertTo-SecureString $NewPwd -AsPlainText -Force) -Reset
<h2 id="zhdat-minimum-10-chasov-ili-srok-replikatsii-srok-tiketa">Ждать минимум 10 часов (или срок репликации + срок тикета)</h2>
<h2 id="shag-2-vtoroy-sbros-parolya-obyazatelen">Шаг 2: Второй сброс пароля (обязателен!):</h2>
$NewPwd2 = [System.Web.Security.Membership]::GeneratePassword(64, 8)
Set-ADAccountPassword -Identity krbtgt -NewPassword (ConvertTo-SecureString $NewPwd2 -AsPlainText -Force) -Reset
Write-Host "krbtgt сброшен. Убедитесь, что изменения реплицированы на все DC."
13. Практический кейс: полный аудит от нуля до отчёта
Ситуация: После уведомления от SOC о подозрительной активности требуется провести аудит AD для поиска возможных backdoor-аккаунтов.
Шаг 1: Быстрая инвентаризация (15 минут)
powershell
<h2 id="zapustit-sbornyy-skript-bystroy-inventarizatsii">Запустить сборный скрипт быстрой инвентаризации:</h2>
$AuditDate = Get-Date -Format "yyyyMMdd_HHmm"
$OutputPath = "C:\ADaudit_$AuditDate"
New-Item -ItemType Directory -Path $OutputPath | Out-Null
<h2 id="1-chleny-domain-admins-rekursivno">1. Члены Domain Admins (рекурсивно):</h2>
Get-ADGroupMember "Domain Admins" -Recursive |
Where-Object objectClass -eq "user" |
ForEach-Object { Get-ADUser $_.SamAccountName -Properties LastLogonDate, Enabled, WhenCreated } |
Export-Csv "$OutputPath\DA_members.csv" -Encoding UTF8 -NoTypeInformation
<h2 id="2-akkaunty-s-admincount-1">2. Аккаунты с AdminCount=1:</h2>
Get-ADUser -Filter {AdminCount -eq 1} -Properties AdminCount, LastLogonDate, WhenChanged |
Export-Csv "$OutputPath\AdminCount1.csv" -Encoding UTF8 -NoTypeInformation
<h2 id="3-akkaunty-s-sid-history">3. Аккаунты с SID History:</h2>
Get-ADUser -Filter * -Properties SIDHistory |
Where-Object { $_.SIDHistory.Count -gt 0 } |
Select-Object Name, SamAccountName, @{N='SIDHistory';E={$_.SIDHistory -join ";"}} |
Export-Csv "$OutputPath\SIDHistory.csv" -Encoding UTF8 -NoTypeInformation
Write-Host "Базовые данные сохранены в $OutputPath"
Шаг 2: BloodHound-сбор и анализ (30 минут)
powershell
<h2 id="na-domen-chlene-ot-privilegirovannogo-akkaunta">На домен-члене, от привилегированного аккаунта:</h2>
.\SharpHound.exe --CollectionMethods All --OutputDirectory $OutputPath
<h2 id="zagruzit-zip-v-bloodhound">Загрузить ZIP в BloodHound</h2>
<h2 id="vypolnit-zaprosy-v-bloodhound">Выполнить запросы в BloodHound:</h2>
<h2 id="1-find-shortest-paths-to-domain-admins">1. Find Shortest Paths to Domain Admins</h2>
<h2 id="2-users-with-foreign-domain-group-membership">2. Users with Foreign Domain Group Membership</h2>
<h2 id="3-find-principals-with-dcsync-rights">3. Find Principals with DCSync Rights</h2>
<h2 id="4-find-all-paths-from-domain-users-to-high-value-targets">4. Find All Paths from Domain Users to High Value Targets</h2>Шаг 3: Анализ Event Log (20 минут)
powershell
<h2 id="izmeneniya-v-da-gruppe-za-poslednie-30-dney">Изменения в DA-группе за последние 30 дней:</h2>
Get-WinEvent -ComputerName $DC -FilterHashtable @{
LogName='Security'; Id=@(4728,4729,4720)
StartTime=(Get-Date).AddDays(-30)
} | Export-Csv "$OutputPath\GroupChanges.csv" -Encoding UTF8 -NoTypeInformation
Шаг 4: PingCastle (10 минут)
text
.\PingCastle.exe --healthcheck --server $Domain
Сохранить HTML-отчёт в $OutputPath
Результат аудита
text
В конкретном кейсе обнаружено:
1. ⚠️ Аккаунт svc_backup_agent состоит в DA:
→ Создан 3 недели назад
→ Имя имитирует сервисный аккаунт
→ PasswordNeverExpires = True
→ Последний вход: сегодня в 02:47 (нерабочее время!)
ВЫВОД: Backdoor-аккаунт
2. ⚠️ Аккаунт john.smith имеет SID History:
→ SID = S-1-5-21-<domain>-512 (Domain Admins!)
→ john.smith не числится в Domain Admins
→ sIDHistory изменён 2 недели назад (совпадает с инцидентом)
ВЫВОД: SID History backdoor
3. ⚠️ Аккаунт helpdesk_lead01 имеет WriteDACL на Domain Admins:
→ Может в любой момент добавить себя в DA
→ Это ЛАТЕНТНАЯ привилегия, не активная
ВЫВОД: Misconfiguration / потенциальный backdoor
14. FAQ: 12 горячих вопросов об аудите привилегированных аккаунтов AD
Q 01 Нужны ли права Domain Admin для аудита с BloodHound?
A SharpHound собирает данные о правах AD, активных сессиях и прочем с правами обычного пользователя домена. Большинство аудиторских запросов — тоже. Domain Admin нужен для анализа ACL AdminSDHolder, чтения атрибута sIDHistory и доступа к Security Event Log на DC.
Q 02 Что делать с аккаунтами с AdminCount=1, которые не состоят в привилегированных группах?
A Это нормальный артефакт: при удалении пользователя из привилегированной группы AdminCount не сбрасывается автоматически. Два варианта: игнорировать (задокументировав) или сбросить вручную. При IR-расследовании все такие аккаунты требуют проверки: сравнить с ожидаемым списком привилегированных пользователей.
Q 03 Как часто проводить аудит привилегированных аккаунтов AD?
A Минимум: раз в квартал — полный аудит через BloodHound + PingCastle. Непрерывно: мониторинг через scheduled-task PowerShell на изменения DA-группы (алерт в реальном времени). После любого инцидента с компрометацией — немедленный полный аудит.
Q 04 BloodHound создаёт много шума в сети — как снизить заметность при аудите?
A Существуют два подхода к сбору SharpHound: полный (All) — шумный, но полный; и тихий через LDAP-запросы без активного сканирования хостов. Для внутреннего аудита полный режим предпочтителен. При угрозе обнаружения активной атаки — LDAP-only.
Q 05 Чем BloodHound Community Edition (CE) отличается от старого BloodHound 4.x?
A BloodHound CE (версия 5+, от SpecterOps) — переработанная версия с расширенным анализом Azure/Entra ID, улучшенным UI и API. Разворачивается через Docker Compose. Классический BloodHound 4.x работает с Neo4j напрямую. Для корпоративного использования рекомендуется CE; для быстрых проверок оба варианта эквивалентны.
Q 06 Почему опасен аккаунт с WriteDACL на Domain Admins, даже если он не состоит в DA?
A WriteDACL позволяет изменить ACL группы Domain Admins. Атакующий с этим правом может добавить себе право AddMember и затем добавить себя в DA. Это двухшаговая эскалация, которая занимает секунды. Именно такие многошаговые пути через изменение прав составляют сложные цепочки атаки, которые BloodHound помогает выявить.
Q 07 Как найти аккаунты с DCSync-правами кроме DA?
A Права DCSync — это расширенные права GetChanges и GetChangesAll на объекте домена (не на группе). PowerShell: анализировать `nTSecurityDescriptor` корневого объекта домена на наличие ACE с GUID `1131f6aa` и `1131f6ad`. BloodHound: запрос «Find Principals with DCSync Rights».
Q 08 Безопасно ли запускать SharpHound в продакшн-домене?
A SharpHound — не малвари, он использует только стандартные LDAP-запросы и WMI-вызовы. Однако он имеет AV-сигнатуры как «инструмент атаки». Антивирусы реагируют на BloodHound и SharpHound как на потенциально опасные инструменты, потому что атакующие действительно их используют. Решение: добавить в AV-исключения на время аудита или запускать с изолированной машины.
Q 09 Что такое «производные» права локального администратора и почему они опасны?
A Производные права — когда пользователь не состоит напрямую в локальной группе Administrators, но получает эти права через вложенные группы AD. Именно так BloodHound обнаружил два аккаунта с правами локального администратора на DC, которые не входили в Domain Admins. Права на DC эквивалентны правам DA.
Q 10 Нужно ли сбрасывать пароль krbtgt при каждом инциденте компрометации DA?
A Да, при любом подтверждённом доступе атакующего к DA-аккаунтам — обязательно. Без этого Golden Ticket-атаки остаются возможными ещё 10 лет (стандартный срок действия атрибута MaxTicketAge). Сброс дважды с интервалом — не бюрократия, а технически необходимо.
Q 11 Как выстроить Tier Model для минимизации привилегий в AD?
A Microsoft рекомендует трёхуровневую модель (Active Directory Tier Model): Tier 0 — контроллеры домена и привилегированные административные хосты; Tier 1 — серверы приложений; Tier 2 — рабочие станции. Аккаунты Tier 0 используются только на Tier 0-хостах. Это значительно ограничивает lateral movement.
Q 12 Могут ли компьютерные аккаунты (не пользователи) иметь скрытые привилегии?
A Да. Компьютерные аккаунты с Unconstrained Delegation могут использоваться для компрометации других аккаунтов. Компьютер-член группы с DA-привилегиями — опасная конфигурация. Хосты с локальным администратором DC-уровня — тоже вектор атаки. BloodHound показывает пути через компьютерные аккаунты наравне с пользовательскими.
15. Чек-лист: аудит привилегированных аккаунтов AD за один рабочий день
Утро: инвентаризация (2–3 часа)
- ☐ Запустить сборный PowerShell-скрипт инвентаризации
- ☐ Экспортировать членов всех привилегированных групп (рекурсивно)
- ☐ Найти аккаунты с AdminCount=1 и не состоящие в явных привилегированных группах
- ☐ Найти аккаунты с непустым SID History
- ☐ Найти сервисные аккаунты в DA (паттерн имени)
- ☐ Найти неактивные аккаунты с привилегиями (нет входа > 90 дней)
День: BloodHound и глубокий анализ (2–3 часа)
- ☐ Запустить SharpHound с правами DA от привилегированного PAW
- ☐ Загрузить данные в BloodHound CE
- ☐ Выполнить запрос: Shortest Paths to Domain Admins
- ☐ Выполнить запрос: Find Principals with DCSync Rights
- ☐ Выполнить запрос: Users with AdminCount=1 (не в явных группах)
- ☐ Проверить производные права локального администратора на DC
- ☐ Проанализировать ACL AdminSDHolder на нестандартные записи
- ☐ Запустить PingCastle и сохранить HTML-отчёт
После обеда: Event Log и SAM (1–2 часа)
- ☐ Проверить Event 4728/4732/4756 за последние 30 дней (добавления в группы)
- ☐ Проверить Event 4720 за последние 30 дней (создание аккаунтов)
- ☐ Проверить Event 4672 за последние 7 дней (вход с привилегиями)
- ☐ Проверить локальных администраторов на критичных серверах (DC, Exchange, PKI)
Итог: отчёт и рекомендации
- ☐ Классифицировать находки: backdoor / misconfiguration / устаревший конфиг
- ☐ Для каждой критической находки: деактивировать аккаунт + уведомить руководство
- ☐ Составить список рекомендаций по устранению с приоритетами
- ☐ Запланировать следующий аудит (максимум через 90 дней)
16. Заключение и теги
Поиск скрытых привилегированных аккаунтов в AD — не разовое мероприятие, а непрерывный процесс. Active Directory — динамическая система: права и членства меняются постоянно, и то, что было безопасным вчера, может стать backdoor завтра.
Организации, которые проактивно проводят аудит и устранение рисков привилегированных аккаунтов с использованием open-source инструментов, защищают себя от того, чтобы стать следующим заголовком о ransomware.
Три практических шага, которые можно сделать сегодня: запустить PingCastle на домене — он покажет риск-скор и топ-проблемы за 15 минут; выполнить рекурсивное `Get-ADGroupMember -Recursive` для Domain Admins и найти аккаунты, которых там не ожидали; настроить PowerShell-мониторинг изменений DA-группы со срабатыванием по email.
> 🔐 Каждый неизвестный администратор — это открытая дверь. Аудит — это инвентаризация ключей.