- PVSM.RU - https://www.pvsm.ru -

Рано или поздно в ходе пентеста встает задача компрометации всего леса — при условии, что есть какие-либо права в одном из доменов. В такие моменты возникает куча вопросов о трастах, их свойствах и самих атаках. Попробуем во всем этом разобраться.
Доверие между доменами используется для прохождения аутентификации пользователей одного домена на контроллере другого домена. Иначе говоря, чтобы пользователи с домена А могли иметь доступ к ресурсам домена Б. Доменная структура может быть двух видов:

При создании дерева доменов между доменами по умолчанию устанавливаются транзитивные доверительные отношения. Все компьютеры имеют общие:
Деревья доменов могут объединяться в леса. При создании леса доменов устанавливаются транзитивные доверительные отношения, и все компьютеры в лесу имеют общие:
Ниже представлена таблица с типами доверия между доменами и их свойствами.
| № | Trust Type | Transitivity | Direction | Authentication Mechanism | Description |
| 1 | External | Non-transitive | One-way or two-way | NTLM Only | Устанавливаются между доменами, принадлежащими к разным лесам, либо c доменом Windows NT 4.0. |
| 2 | Realm | Transitive or non-transitive | One-way or two-way | Kerberos Only | Устанавливаются между Windows и не Windows доменами, использующими протокол Kerberos. Данный тип доверительных отношений может использоваться для обеспечения сквозной аутентификации на Windows и UNIX-системах. |
| 3 | Forest | Transitive | One-way or two-way | Kerberos or NTLM | Устанавливаются между лесами. При этом администраторы сами решают, какими будут отношения — двусторонними или односторонними. |
| 4 | Shortcut | Transitive | One-way or two-way | Kerberos or NTLM | Устанавливаются между доменами различных деревьев, принадлежащих к одному лесу. Используются для уменьшения пути доверия, тем самым повышая эффективность взаимодействия между двумя доменами. |
| 5 | Parent-Child | Transitive | Two-way | Kerberos or NTLM | Устанавливаются автоматически при создании в дереве нового домена. В рамках дерева доменов отношения описываются схемой Parent-Child. |
| 6 | Tree-Root Trust | Transitive | Two-way | Kerberos or NTLM | Устанавливаются автоматически при создании в существующем лесе нового дерева доменов. Фактически доверительные отношения устанавливаются между корневым доменом леса и создаваемым доменом, который будет являться корневым для нового дерева. |
Более наглядно типы доверий между доменами проиллюстрированы на картинке ниже.

Транзитивность нужна для определения доверия за пределами двух доменов, между которыми оно было сформировано, и используется для расширения отношений доверия с другими доменами. Если мы добавляем к домену дочерний домен, между родительским и дочерним доменами устанавливаются двусторонние доверительные отношения. Эти отношения транзитивны, т.е. если домен A доверяет домену D и домен D доверяет домену E, то домен A доверяет и домену E.

Нетранзитивное доверие можно использовать для отказа доверия с другими доменами.
Путь доверительных отношений — это ряд доверительных отношений между доменами, к которому должны поступать запросы на проверку подлинности. Иными словами, прежде чем аутентифицировать пользователя, определяется доверие между доменами. Чтобы пользователи домена A могли получить доступ к ресурсам домена D, домен D должен доверять домену A.
Направление доверия бывает двух типов:
Одностороннее доверие — это однонаправленный путь проверки подлинности, который создается между двумя доменами. В однонаправленном доверии между доменом A и доменом B пользователи в домене B имеют доступ к ресурсам в домене A. Однако пользователи в домене A не имеют доступа к ресурсам в домене B. Такой тип доверия не транзитивен.
Двустороннее доверие — это комбинация двух однонаправленных доверительных отношений. В двунаправленном доверии между доменами A и B их пользователи имеют доступ к ресурсам обоих доменов. Такой тип доверия транзитивен.
Направление доверия всегда противоположно направлению доступа. Показательная схема от Microsoft ниже:

Ссылки для более глубокого ознакомления с типами доверий:
Рассмотрим пример. Client пытается получить доступ к Server.
Изменения начинаются с пункта 4: появляется inter-realm TGT-тикет, так называемый реферальный тикет, который шифруется/подписывается inter-realm ключом, создаваемым из доверенного пароля. Доверенный пароль задается при установке доверительных отношений и известен обоим контроллерам домена. Используя inter-realm TGT-тикет, пользователь домена 1 может запросить TGS-тикет для доступа к ресурсам домена 2.


6-8. Ответ с решением об аутентификации клиента.
Итак, для проведения атаки нам потребуется информация о доверительных отношениях в нашем домене.
Существует 3 основных метода для перечисления трастов в домене:
Win32 API
Перечисление осуществляется с помощью вызова функции DsEnumerateDomainTrusts [5], которая возвращает структуру DS_DOMAIN_TRUSTSA [6]. При использовании данного метода возвращается SID и GUID целевого домена, флаги [7] и атрибуты [8], характеризующие текущие доверительные отношения в домене.
| DS_DOMAIN_DIRECT_INBOUND | Enumerate domains that directly trust the domain which has ServerName as a member. |
| DS_DOMAIN_DIRECT_OUTBOUND | Enumerate domains directly trusted by the domain which has ServerName as a member. |
| DS_DOMAIN_IN_FOREST | Enumerate domains that are a member of the same forest which has ServerName as a member. |
| DS_DOMAIN_NATIVE_MODE | Enumerate domains where the primary domain is running in Windows 2000 native mode. |
| DS_DOMAIN_PRIMARY | Enumerate domains that are the primary domain of the domain which has ServerName as a member. |
| DS_DOMAIN_TREE_ROOT | Enumerate domains that are at the root of the forest which has ServerName as a member. |
| TRUST_ATTRIBUTE_NON_TRANSITIVE | Disallow transitivity. |
| TRUST_ATTRIBUTE_UPLEVEL_ONLY | The trust link is not valid for client operating systems earlier than Windows 2000. |
| TRUST_ATTRIBUTE_FILTER_SIDS | Quarantine domains. |
| TRUST_ATTRIBUTE_FOREST_TRANSITIVE | The trust link may contain forest trust information. |
| TRUST_ATTRIBUTE_CROSS_ORGANIZATION | This trust is to a domain/forest that is not part of this enterprise. |
| TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL | Trust is treated as external for trust boundary purposes. |
| TRUST_ATTRIBUTE_WITHIN_FOREST | Trust is internal to this forest. |
BloodHound [9] собирает информацию с помощью метода Win32 API.

.Net
Используется метод GetCurrentDomain [10]из пространства имен [System.DirectoryServices.ActiveDirectory.Domain], который возвращает экземпляр класса System.DirectoryServices.ActiveDirectory.Domain [11]. В этом классе реализован метод GetAllTrustRelationships [12], который возвращает все доверительные отношения для текущего домена.
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
Использование данного метода реализовано в модуле Get-DomainTrust в PowerView [13].

Одним из преимуществ этого метода является его простота. Информацию легко читать и понимать, но ее объем значительно меньше, чем при выполнении перечисления другими методами.
LDAP
Информация о доверительных отношениях домена хранится в Active Directory как objectClass класса trustedDomain [14].
Пример использования:
dsquery * -filter "(objectClass=trustedDomain)" -attr *

PowerView [13] по умолчанию использует данный метод.

Имея информацию о доменах и типах доверия, можно переходить непосредственно к самой атаке. Рассмотрим 2 варианта:
В зависимости от домена, который был скомпрометирован, можно выделить несколько векторов атак:
| № | Стартовый домен. Позиция атакующего | Атакуемый домен | Техника атаки | Доверительные отношения |
| 1 | Root | Child | Golden Ticket + Enterprise Admin Group | Inter-realm (2-way) |
| 2 | Child | Child | Эксплуатация SID History | Inter-realm Parent-Child (2-way) |
| 3 | Child | Root | Эксплуатация SID History Эксплуатация билетов доверия |
Inter-realm Tree-Root(2-way) |
| 4 | Forest 1 | Forest 2 | Printer Bug | Inter-realm Forest or External trust (2-way) |
Стоит отметить, что для успешной реализации всех векторов необходимо двустороннее доверие между доменами.
SID History [15] был введен для облегчения миграции пользователей из одного домена в другой. Атрибут cодержит в себе предыдущие SID объекты. Каждый раз, когда объект перемещается из одного домена в другой, создается новый SID, который становится objectSID. Предыдущий SID добавляется в свойство sIDHistory.
В каждом лесу есть группа пользователей Enterprise Admins, которая существует только в root-домене и имеет права локального администратора на контроллерах домена всех Child-доменов леса. Впервые данная атака был продемонстрирована Sean Metcalf [16] на BlackHat USA 2015 [17]. Суть атаки в том, что мы выпускаем Golden-тикет с добавлением дополнительного SID группы Enterprise Admins. Это выполняется путем добавления ExtraSids в структуре KERB_SID_AND_ATTRIBUTES [18], которая отправляется в структуре KERB_VALIDATION_INFO [18].

Демонстрация атаки:

В impacket [19] есть скрипт [20], который все это автоматизирует.
Имея права администратора в Root-домене, мы можем создать Golden Ticket с добавлением пользователя в группу Enterprise Admins (519).
Kerberos::golden /domain:<domain> /sid:<domain_SID> /krbtgt:<ntlm_hash_krbtgt_user> /user:<user> /groups:500,501,513,512,520,518,519 /ptt
Как было написано выше, Enterprise Admin имеет права локального администратора на DC Child-доменов. Таким образом нам удастся скомпрометировать в лесу все Child-домены.
Для доступа к какому-либо ресурсу по протоколу Kerberos, необходим TGS-тикет, который шифруется NTLM-хешем пароля сервисной учетной записи. Контроллер домена хранит хеши паролей пользователей только своего домена, поэтому, когда пользователю из домена А нужен доступ к ресурсу в домене Б, используется inter-realm key. Данный ключ создается на основе доверенного пароля, который устанавливается при создании доверительных отношений между доменами в одном лесу. В базе паролей (NTDS.dit) на контроллере домена можно найти пользователей со знаком $ на конце. Их пароль и используется для создания inter-realm ключей. Для создания inter-realm TGT-тикета нам необходим хеш пароля этой учетной записи.
Kerberos::golden /user:<user> /domain:<domain> /sid:<sid_domain> /sids:<extra_sid_entrprice_admin_group_from _another_domain> /aes256:<aes256_trust_user_password> /service:krbtgt /target:<target_domain> /ptt
Демонстрация атаки:

Атака особенно актуальна, когда служба ИБ заметила угрозу и сменила пароль krbtgt 2 раза. В этом случае мы сможем создавать golden-тикеты, используя доверенный пароль между доменами.
В Windows Print System Remote Protocol (MS-RPRN) есть метод RpcRemoteFindFirstPrinterChangeNotification(Ex), включенный по умолчанию, который позволяет принудительно выполнить аутентификацию на любом компьютере с запущенной службой Spooler на указанном хосте по протоколу Kerberos либо NTLM. В случае c NTLM мы можем выполнить NTLM-relay, либо начать брутить пароль компьютера (никогда не сбрутите). В случае с Kerberos необходима скомпрометированная машина с неограниченным делегированием. Тогда мы сможем забрать TGT-тикет и развить атаку.
Демонстрация атаки:

Рисунок ниже демонстрирует этапы, показанные на видео.

Немного теории. Carlos Garsia [21] в своем докладе [22] привел отличную таблицу, которая иллюстрирует свойства разных типов групп.

Из особенностей стоит учитывать, что в глобальный каталог группы типа AD Domain Local и AD Global реплицируются без членов групп, а группы типа AD Universal реплицируется вместе с пользователями. [23]
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).
В случае, если у нас нет прав администратора домена, выполняем перечисление объектов. Нас интересуют:
Поиск пользователей из другого домена, являющихся локальными администраторами на хостах в нашем домене в 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 [13]:
Get-NetLocalGroupMember <server>
Как уже говорилось выше, в глобальный каталог реплицируются пользователи, состоящие только в группах типа 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 [13]:
Get-DomainForeignUser -Domain <Domain>
Get-DomainForeignGroupMember -Domain <Domain>


Дескриптор безопасности 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 [24] в совем блоге [25]. Также 9 июля компания Microsoft выпустила обновление [26], которое отключает TGT-делегирование между лесами по умолчанию. Теперь всё, история с неограниченным делегированием и компрометацией одного леса из другого при используемом протоколе Kerberos больше не работает.
Автор: Сергей Ефимов
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/329231
Ссылки в тексте:
[1] External Trust: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc732859%28v%3dws.10%29
[2] Realm: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc731297%28v%3dws.10%29
[3] Forest: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771397%28v%3dws.10%29
[4] Shortcut: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc754538%28v%3dws.10%29
[5] DsEnumerateDomainTrusts: https://docs.microsoft.com/ru-ru/windows/win32/api/dsgetdc/nf-dsgetdc-dsenumeratedomaintrustsa
[6] DS_DOMAIN_TRUSTSA: https://docs.microsoft.com/ru-ru/windows/win32/api/dsgetdc/ns-dsgetdc-ds_domain_trustsa
[7] флаги: https://msdn.microsoft.com/en-us/library/ms675976(v=vs.85).aspx
[8] атрибуты: https://docs.microsoft.com/ru-ru/windows/win32/api/ntsecapi/ns-ntsecapi-trusted_domain_information_ex
[9] BloodHound: https://github.com/BloodHoundAD/BloodHound
[10] GetCurrentDomain: https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectory.domain.getcurrentdomain?redirectedfrom=MSDN&view=netframework-4.8
[11] System.DirectoryServices.ActiveDirectory.Domain: https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.activedirectory.domain?redirectedfrom=MSDN&view=netframework-4.8
[12] GetAllTrustRelationships: https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.domain.getalltrustrelationships(v=vs.110).aspx),
[13] PowerView: https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1
[14] trustedDomain: https://docs.microsoft.com/ru-ru/windows/win32/adschema/c-trusteddomain
[15] SID History: https://docs.microsoft.com/en-us/windows/win32/adschema/a-sidhistory
[16] Sean Metcalf : https://twitter.com/PyroTek3
[17] BlackHat USA 2015: https://www.blackhat.com/docs/us-15/materials/us-15-Metcalf-Red-Vs-Blue-Modern-Active-Directory-Attacks-Detection-And-Protection.pdf
[18] KERB_SID_AND_ATTRIBUTES: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/69e86ccc-85e3-41b9-b514-7d969cd0ed73
[19] impacket: https://github.com/SecureAuthCorp/impacket
[20] скрипт: https://github.com/SecureAuthCorp/impacket/blob/master/examples/raiseChild.py
[21] Carlos Garsia: https://twitter.com/ciyinet
[22] докладе: https://www.youtube.com/watch?v=6aV5tZlQ2EQ
[23] что в глобальный каталог группы типа AD Domain Local и AD Global реплицируются без членов групп, а группы типа AD Universal реплицируется вместе с пользователями.: https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc759007(v=ws.10)
[24] dirkjan: https://twitter.com/_dirkjan
[25] блоге: https://dirkjanm.io/active-directory-forest-trusts-part-one-how-does-sid-filtering-work/
[26] обновление : https://support.microsoft.com/en-us/help/4490425/updates-to-tgt-delegation-across-incoming-trusts-in-windows-server
[27] Источник: https://habr.com/ru/post/466445/?utm_source=habrahabr&utm_medium=rss&utm_campaign=466445
Нажмите здесь для печати.