Проблема
Классический vulnerability scan хорошо ловит непропатченные CVE, но почти не видит misconfiguration в AD — а именно они чаще всего дают путь от обычного пользователя до Domain Admin. Слабые ACL на объектах, service-аккаунты с SPN и простым паролем, неограниченное делегирование (unconstrained delegation), избыточные права на репликацию — всё это «фичи», а не баги, поэтому классический сканер их не находит.
Второй, более тонкий момент: даже когда отдельные слабости находят, их часто описывают изолированно — «найден аккаунт со слабым паролем», «найден SPN». Реальный риск виден только тогда, когда эти находки соединены в цепочку: слабость №1 даёт доступ, который делает возможным использование слабости №2, и так далее до контроллера домена.
Решение
Аудит AD стоит строить по фазам, соответствующим реальной последовательности атаки, и на каждой фазе фиксировать evidence — не «в теории возможно», а «команда выполнена, результат такой-то»:
- Reconnaissance (T1087.002) — enumeration пользователей, групп, компьютеров через LDAP-запросы. Инструменты вроде BloodHound строят граф, а не список.
- ACL abuse (T1222.001) — поиск объектов, где непривилегированный принципал имеет
GenericAll,WriteDACLилиForceChangePasswordна более привилегированный объект. - Kerberoasting (T1558.003) — запрос TGS-тикетов для аккаунтов с SPN и offline-подбор пароля из хэша тикета. Работает против любого аутентифицированного пользователя домена без дополнительных прав.
- DCSync (T1003.006) — если принципал получил права на репликацию (
Replicating Directory Changes), можно запросить хэши паролей всех пользователей домена, включая krbtgt.
Каждая фаза проверяется отдельно и помечается статусом: подтверждено с доказательством, предпосылки есть но не подтверждено, не применимо. Так видно не просто «домен уязвим», а конкретно каким шагом и с какого стартового доступа.
Что проверить руками
- Построить граф ACL от низкопривилегированной группы (например, Domain Users) до Domain Admins.
- Список service-аккаунтов с SPN — есть ли слабые/незменяемые пароли, PASSWORD_NEVER_EXPIRES.
- Компьютеры и сервисные аккаунты с unconstrained delegation.
- Кто имеет право
Replicating Directory Changes/Replicating Directory Changes Allпомимо штатных DC. - GPO с правами на запись у непривилегированных групп — путь к массовому выполнению кода.
- krbtgt: возраст пароля — если не менялся годами, Golden Ticket остаётся рабочим даже после сброса паролей пользователей.
Безопасный пример кода
Read-only PowerShell-проверка на предпосылки Kerberoasting: ищет аккаунты с SPN, не отключённые и с флагом «пароль не истекает» — без запроса самих TGS-тикетов и без офлайн-подбора. Только сбор сигналов для приоритизации ручной проверки.
Import-Module ActiveDirectory
Get-ADUser -Filter {ServicePrincipalName -like "*"} -Properties ServicePrincipalName, PasswordNeverExpires, PasswordLastSet, Enabled |
Where-Object { $_.Enabled -eq $true } |
Select-Object Name, PasswordNeverExpires, PasswordLastSet, @{N="SPNCount";E={$_.ServicePrincipalName.Count}} |
Sort-Object PasswordLastSet |
Format-Table -AutoSize
# отдельно: возраст пароля krbtgt — индикатор риска Golden Ticket
Get-ADUser krbtgt -Properties PasswordLastSet | Select-Object Name, PasswordLastSet
Как это должно попасть в отчёт
- Signals: слабые ACL на пути к privileged-группам, service-аккаунты с SPN и старым паролем, unconstrained delegation, широкие права на репликацию.
- Controls: managed service accounts (gMSA) вместо ручных SPN-паролей, Tiering-модель администрирования, регулярная ротация krbtgt, аудит ACL-изменений.
- Retest: тот же граф ACL после исправления не должен показывать путь от низкопривилегированной точки входа до Domain Admin.