Атаки на трасты между доменами
В случае аутентификации между трастами выполняется следующая логика:
- Проверяется Direction Trust Relationships (направление доверительных отношений).
- На контроллер домена A отправляются учетные данные клиента для прохождения аутентификации.
- Если доверительных отношений нет, то проверяется Transitivity (транзитивность) с доменом A.
- Проверка Transitivity (транзитивность) между доменами
- Если транзитивность между доменами есть, то передается запрос аутентификации следующему домену в пути доверия. Этот контроллер домена повторяет процесс, проверяя учетные данные пользователя по своей базе данных учетных записей безопасности.
- Если транзитивности нет, клиенту возвращается сообщение об отказе в доступе.
6–8. Ответ с решением об аутентификации клиента.
Итак, для проведения атаки нам потребуется информация о доверительных отношениях в нашем домене.
Перечисление трастов
Существует 3 основных метода для перечисления трастов в домене:
- через Win32 API;
- через .NET методы;
- через LDAP.
Win32 API
Перечисление осуществляется с помощью вызова функции DsEnumerateDomainTrusts, которая возвращает структуру DS_DOMAIN_TRUSTSA. При использовании данного метода возвращается SID и GUID целевого домена, флаги и атрибуты, характеризующие текущие доверительные отношения в домене.
BloodHound собирает информацию с помощью метода Win32 API.
.Net
Используется метод GetCurrentDomainиз пространства имен [System.DirectoryServices.ActiveDirectory.Domain], который возвращает экземпляр класса System.DirectoryServices.ActiveDirectory.Domain. В этом классе реализован метод GetAllTrustRelationships, который возвращает все доверительные отношения для текущего домена.
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
Использование данного метода реализовано в модуле Get-DomainTrust в PowerView.
Одним из преимуществ этого метода является его простота. Информацию легко читать и понимать, но ее объем значительно меньше, чем при выполнении перечисления другими методами.
LDAP
Информация о доверительных отношениях домена хранится в Active Directory как objectClass класса trustedDomain.
Пример использования:
dsquery * -filter "(objectClass=trustedDomain)" -attr *
PowerView по умолчанию использует данный метод.
Имея информацию о доменах и типах доверия, можно переходить непосредственно к самой атаке. Рассмотрим 2 варианта:
- Нам удалось скомпрометировать домен, и мы имеем права администратора домена.
- У нас нет прав администратора домена.
С правами администратора одного из доменов
В зависимости от домена, который был скомпрометирован, можно выделить несколько векторов атак:
Стоит отметить, что для успешной реализации всех векторов необходимо двустороннее доверие между доменами.
1. Эксплуатация SID History
SID History был введен для облегчения миграции пользователей из одного домена в другой. Атрибут cодержит в себе предыдущие SID объекты. Каждый раз, когда объект перемещается из одного домена в другой, создается новый SID, который становится objectSID. Предыдущий SID добавляется в свойство sIDHistory.
В каждом лесу есть группа пользователей Enterprise Admins, которая существует только в root-домене и имеет права локального администратора на контроллерах домена всех Child-доменов леса. Впервые данная атака был продемонстрирована Sean Metcalf на BlackHat USA 2015. Суть атаки в том, что мы выпускаем Golden-тикет с добавлением дополнительного SID группы Enterprice Admins. Это выполняется путем добавления ExtraSids в структуре KERB_SID_AND_ATTRIBUTES, которая отправляется в структуре KERB_VALIDATION_INFO.
Демонстрация атаки:
В impacket есть скрипт, который все это автоматизирует.
2. Golden Ticket + Enterprice Admin Group
Имея права администратора в Root-домене, мы можем создать Golden Ticket с добавлением пользователя в группу Enterprice Admins (519).
Kerberos::golden /domain: /sid: /krbtgt: /user: /groups:500,501,513,512,520,518,519 /ptt
Как было написано выше, Enterprice Admin имеет права локального администратора на DC Child-доменов. Таким образом нам удастся скомпрометировать в лесу все Child-домены.
3. Эксплуатация билетов доверия
Для доступа к какому-либо ресурсу по протоколу Kerberos, необходим TGS-тикет, который шифруется NTLM-хешем пароля сервисной учетной записи. Контроллер домена хранит хеши паролей пользователей только своего домена, поэтому, когда пользователю из домена А нужен доступ к ресурсу в домене Б, используется inter-realm key. Данный ключ создается на основе доверенного пароля, который устанавливается при создании доверительных отношений между доменами в одном лесу. В базе паролей (NTDS.dit) на контроллере домена можно найти пользователей со знаком $ на конце. Их пароль и используется для создания inter-realm ключей. Для создания inter-realm TGT-тикета нам необходим хеш пароля этой учетной записи.
Kerberos::golden /user: /domain: /sid: /sids: /aes256: /service:krbtgt /target: /ptt
Демонстрация атаки:
Атака особенно актуальна, когда служба ИБ заметила угрозу и сменила пароль krbtgt 2 раза. В этом случае мы сможем создавать golden-тикеты, используя доверенный пароль между доменами.
4. Printer Bug
В Windows Print System Remote Protocol (MS-RPRN) есть метод RpcRemoteFindFirstPrinterChangeNotification (Ex), включенный по умолчанию, который позволяет принудительно выполнить аутентификацию на любом компьютере с запущенной службой Spooler на указанном хосте по протоколу Kerberos либо NTLM. В случае c NTLM мы можем выполнить NTLM-relay, либо начать брутить пароль компьютера (никогда не сбрутите). В случае с Kerberos необходима скомпрометированная машина с неограниченным делегированием. Тогда мы сможем забрать TGT-тикет и развить атаку.
Демонстрация атаки:
Рисунок ниже демонстрирует этапы, показанные на видео.
У нас нет прав администратора домена
Немного теории. Carlos Garsia в своем докладе привел отличную таблицу, которая иллюстрирует свойства разных типов групп.
Из особенностей стоит учитывать, что в глобальный каталог группы типа AD Domain Local и AD Global реплицируются без членов групп, а группы типа AD Universal реплицируется вместе с пользователями.
Because of the way that groups are enumerated by the Global Catalog, the results of a back-link [i.e. memb search can vary, depending on whether you search the Global Catalog (port 3268) or the domain (port 389), the kind of groups the user belongs to (global groups vs. domain local groups).
В случае, если у нас нет прав администратора домена, выполняем перечисление объектов. Нас интересуют:
- Пользователи другого домена, которые имеют права локального администратора на машинах в нашем домене.
- Пользователи из других доменов, состоящие в группах домена пользователя. Группы, содержащие пользователей из другого домена.
- Foreign ACL Principals.
1. Пользователи другого домена, которые имеют права локального администратора на машинах в нашем домене
Поиск пользователей из другого домена, являющихся локальными администраторами на хостах в нашем домене в BloodHound:
MATCH (c:Computer)
OPTIONAL MATCH p1 = (u1)-[:AdminTo]->(c)
WHERE NOT u1.domain = c.domain
WITH p1,c OPTIONAL MATCH p2 = (u2)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c)
WHERE NOT u2.domain = c.domain
RETURN p1,p2
Команда в PowerView:
Get-NetLocalGroupMember
2. Пользователи из других доменов, состоящие в группах домена пользователя. Группы, содержащие пользователей из другого домена
Как уже говорилось выше, в глобальный каталог реплицируются пользователи, состоящие только в группах типа Universal. Для демонстрации этой особенности выполним запрос групп в глобальном каталоге, содержащих хотя бы одного пользователя и прямой ldap-запрос к контроллеру домена.
Get-DomainGroup -Properties name, grouptype, member, DistinguishedName -LDAPFilter '(member=*)' -SearchBase "GC://jet.lab"
При выполнении запроса к глобальному каталогу, мы видим только одну группу Universal Group c типом AD Universal из домена one.jet.lab.
Если мы выполним прямой LDAP-запрос к домену one.jet.lab, то увидим другие группы с типом AD Domain local и AD Global.
Это важно учитывать при выполнении перечисления пользователей и групп.
Команды в PowerView:
Get-DomainForeignUser -Domain
Get-DomainForeignGroupMember -Domain
3. Foreign ACL Principals
Дескриптор безопасности ntSecurityDescriptor (https://docs.microsoft.com/en-us/windows/win32/adschema/a-ntsecuritydescriptor) доступен для всех пользователей из доверенных доменов и реплицируется в глобальный каталог. Таким образом мы можем запросить все DACL для всех объектов в доверяющих доменах и отфильтровать пользователей из других доменов.
Get-DomainObjectAcl -Domain jet.lab -ResolveGuids | ?{$_.SecurityIdentifier -like ‘SID_Domain*’}
Итак, нам удалось выявить пользователя Mike из домена forestc.lab, который имел права на группу Global Group в домене jet.lab.
P.S. Для защиты между лесами используется SID Filtering и Selective Authentication. Атаку между лесами с включенным SID Filtering привел dirkjan в совем блоге. Также 9 июля компания Microsoft выпустила обновление, которое отключает TGT-делегирование между лесами по умолчанию. Теперь всё, история с неограниченным делегированием и компрометацией одного леса из другого при используемом протоколе Kerberos больше не работает.