Привет, Хабр!
Сегодня мы хотим поговорить об атаке с применением известной техники Golden Ticket (T1558.001). О том, что лежит в основе Golden Ticket атак и какие механизмы их реализации существуют, написано уже много. Поэтому в этой статье мы сфокусируемся больше на способах детектирования подобных угроз.
Мы разберем публичные примеры детекта Золотых билетов, которые есть в сети, и расскажем о том, почему, как нам кажется, эти методы могут не сработать. А также приведем способ детектирования, который, опираясь на нашу практику, оказался более эффективным для выявления подобных атак. Мы не беремся утверждать, что предложенный нами метод является единственным верным способом детектирования Golden Ticket, скорее альтернативным.
Прежде чем приступить, давайте еще раз вспомним, что такое Kerberos и Golden Ticket, а также какую мотивацию преследует злоумышленник при выполнении этой атаки.
Вспомним про Kerberos
Kerberos – сетевой протокол аутентификации, распространенный в средах Windows Active Directory, позволяет передавать данные через незащищённые сети для безопасной идентификации. Протокол проверки подлинности Kerberos обычно используется для аутентификации на объектах доменной инфраструктуры.
Kerberos предоставляет множество преимуществ, которые помогают сделать аутентификацию безопасной и удобной. Но опытные хакеры могут использовать слабые места в Kerberos для своих злонамеренных целей. Для полного понимания картины атак нам нужно еще вспомнить механизмы работы протокола Kerberos.
При использовании Kerberos пользователи никогда не аутентифицируют себя напрямую в различных необходимых им службах. Вместо этого Центр распространения ключей Kerberos (KDC) функционирует как доверенная сторонняя служба проверки подлинности. Компонентами KDC являются сервер аутентификации (AS, Authentication Server) и сервер выдачи билетов (TGS, Ticket-Granting Service). Он действует как контрольная точка и выдает билеты, удостоверяющие личность пользователя (TGT, Ticket-Granting Ticket), после его аутентификации. Когда пользователю требуется доступ к ресурсам, ему не нужно повторно аутентифицироваться, клиент просто отправляет TGT, чтобы доказать, что он уже недавно это сделал.
Важно отметить, что все TGT билеты KDC шифрует с помощью пароля для специальной учетной записи KRBTG.
Как работает Golden Ticket
Golden Ticket — способ атаки, при которой злоумышленник имеет возможность получить секретный ключ сервисной учётной записи в Active Directory (KRBTGT), он же является тем самым паролем в зашифрованном виде.
Наличие секретного ключа позволяет атакующему использовать его для подделки Ticket- Granting Ticket для аутентификации под любым пользователем домена. Ключом KRBTGT подписываются все TGT в домене. Соответственно, украв этот ключ, злоумышленник сможет подделать любой TGT билет в домене, и он будет принят – так как подпись валидна.
Помимо того, что атакующий может создать TGT для любого пользователя в домене, есть еще одна неприятность: секретный ключ сервиса KRBTGT по умолчанию никогда не меняется, только за исключением случаев, когда контроллер домена (DC) был обновлён, а процедура смены обладает рядом сложностей, что делает эту атаку эффективной для закрепления в домене.
Таким образом, Золотой билет — это поддельный TGT, созданный с помощью украденного ключа KDC.
Давайте здесь остановимся и чуть подробнее разберём, как формируются Ticket-Granting Ticket и Ticket-Granting Service.
Ticket-Granting Ticket (TGT)
TGT или билет, удостоверяющий личность пользователя — по сути является доказательством успешно пройденной аутентификации. Если кратко, то алгоритм получения TGT выглядит следующим образом:
-
Для получения TGT формируется AS_REQ, который направляется на KDC. В качестве последнего в инфраструктуре MS Active Directory выступают контроллеры доменов. В самом AS_REQ фигурируют атрибуты:
User Principal Name
Domain Name (Realm)
Service Principal Name
Copy of the Session Key
Pre-Authentication Timestamp, зашифрованный с помощью ключа, который был создан на основе пароля от учетной записи
-
После проверки наличия пользователя в базе NTDS.dit, расшифровки и сравнении временных меток формируется ответное сообщение AS_REP. Отметим, что только часть сообщения относится непосредственно к TGT. Она как раз зашифрована с помощью ключа KDC, а уже сам ключ сгенерирован на основании пароля от системной учетной записи KRBTGT и уникален для каждого домена. При легитимной ситуации набор атрибутов может быть расшифрован только на контроллере домена. Атрибуты AS REP:
User Principal Name
Domain Name
Service Principal Name
Copy of the Session Key
Privilege Attribute Certificate (PAC)
Time To Live (TTL)
Хотя по умолчанию TGT обычно действительны в течение 10 часов, злоумышленник может сделать их действительным в течение любого промежутка времени, вплоть до 10 лет. По этой причине наличие четкой стратегии для обнаружения, смягчения последствий и устранения этих атак имеет решающее значение.
Ticket-Granting Service (TGS)
TGS называют сервисным билетом, который используется для получения доступа к доменным ресурсам. По умолчанию TGS действителен в течение 10 часов, он не может быть обновлен, а должен каждый раз запрашиваться повторно, в отличие от TGT, в реализованном варианте протокола от Microsoft.
Получение TGS происходит так:
-
Формируется запрос TGS_REQ в сторону KDC с некоторым набором атрибутов, включая TGT:
User Principal Name
Domain Name
Service Principal Name
Ticket-Granting Ticket (TGT)
Pre-Authentication Timestamp
KDC расшифровывает TGT, проверяет временную метку и формирует TGS_REP, который отправляется в сторону клиента. В свою очередь атрибуты, которые относятся к TGS зашифрованы с помощью ключа сервиса.
Примечание: Если злоумышленник имеет ключ сервиса, то он может подделывать TGS для этого сервиса, такая атака называется Silver Ticket.
Механизм атаки
Изучив основные компоненты рабочего процесса проверки подлинности Kerberos, имеющие отношение к атаке Golden Ticket, рассмотрим сам механизм ее использования.
Как уже было сказано, KDC подписывает своим ключом все TGT билеты в домене, поэтому кража этой секретной подписи позволяет подделывать такие билеты. При этом при подделке билетов злоумышленник имеет возможность записать в билете любую информацию. Например, может указать, что обладает правами администратора домена или даже представиться несуществующим пользователем, у которого есть административные права. Это обеспечивает ему беспрепятственный доступ к сетевым ресурсам организации и, пожалуй, самое серьезное, возможность находиться в инфраструктуре длительный период, иногда даже несколько лет, маскируясь под учетные данные пользователей, в том числе и уровня администратора. Эта ситуация имеет место быть, потому что проверка пользователя происходит только на этапе AS_REQ, когда мы предоставляем KDC свои учетные данные: логин и пароль.
Стоит еще раз отметить, что такая атака возможна в связи с архитектурными особенностями протокола Kerberos, так как в данном случае используется подход, при котором все участники доменной инфраструктуры должны доверять KDC, как главному распорядителю ключей и верификатору пользователей. Поэтому нет ничего удивительного в том, что компрометация ключа KDC приведёт и к компрометации всего домена.
Детектирование
Ну а теперь вернемся к основной теме статьи, то есть к самому началу, где мы рассказывали, что в Интернете присутствует множество способов детектирования Golden Ticket.
Ниже мы приводим обезличенные реальные примеры детекта, многие из которых вызывают вопросы, поскольку некоторые способы можно обойти, а другие сообщают не об атаке, а скорее о легитимной деятельности. И дальше финально попытаемся предоставить способ детектирования, который, на наш взгляд, лишен этих недостатков.
Пример детекта 1
Предлагаемый вариант:
Наблюдение за необычной активностью, связанной с Active Directory и Kerberos. Вы можете проводить аудит событий Kerberos AS и TGS на наличие несоответствий. События входа в систему и выхода из системы Windows, которые содержат пустые поля (идентификаторы событий 4624, 4672 и 4634), могут быть индикаторами атаки Golden Ticket или действиями Pass-The-Ticket атаки, связанной с Golden Ticket. Другими индикаторами атаки с использованием Golden Ticket могут быть запросы билетов TGS без предыдущих запросов TGT или билеты TGT с произвольными значениями времени жизни [1].
В чем минусы:
Перечисленные типы событий (4624: An account was successfully logged on, 4672: Special privileges assigned to new logon, 4634: An account was logged off) не содержат каких-либо отличительных строк от обычной аутентификации, потому что TGT и TGS билеты, которые использует злоумышленник являются абсолютно легальными с точки зрения доменных устройств и самого KDC.
Запрос TGS без наличия запроса TGT – это шаг в правильном направлении (об этом будет сказано ниже), но он не является панацей, так как атакующий может подделать TGT, если у него есть пароль любого пользователя (в большинстве случаев это так). Также в домене могут существовать пользователи, для получения билетов, которых не нужен пароль, у этих пользователей в атрибуте UserAccountControl присутствует флаг DONT_REQ_PREAUTH.
Основываться на времени жизни TGT билета ненадёжно, так как атакующий может подставить любое время жизни в TGT билет, включая тот, что применяется в целевом домене.
Пример детекта 2
Предлагаемый вариант:
Рекомендовано проверить логи на наличие пропущенных/изменённых полей, так как обычно логи, связанные с Golden Ticket могут иметь одну из следующих проблем:
Event ID: 4624 (Account Logon)
Необычное поведение заключается в поле Account Domain, которое при атаке содержит полное имя домена, когда там должно быть краткое имя домена.
Пример: имя домена, отображаемое в поле Account Domain: LAB.ADSECURITY.ORG, а должно быть [ADSECLAB].
Event ID: 4672 (Admin Logon)
Необычное поведение заключается в поле Account Domain, при атаке оно пустое, когда там должно быть краткое имя домена.
Пример: имя домена, отображаемое в поле Account Domain: _______________, а должно быть [ADSECLAB] [2]
В чем минус:
Этот способ детекта не будет работать, так как при формировании TGT билета у атакующего есть возможность скорректировать поля, включая имя домена и доменное имя целевого аккаунта.
Пример детекта 3
Предлагаемый вариант:
В качестве еще одного способа обнаружения Golden Ticket вы можете провести мониторинг билетов Kerberos, выданных со значениями срока действия, превышающего максимальное значение, которое разрешено в политике домена. Это позволит обнаружить большинство атак Golden Ticket, но если какие-либо пользователи создадут Золотой билет срок действия которых не превышает разрешенного срока, то они не будут обнаружены. Однако это в значительной степени противоречит цели Golden Ticket — иметь неограниченный административный доступ к домену [3].
В чем минус:
Так как у злоумышленника есть ключ KRBTGT, он не нуждается в создании TGT на очень долгий срок. В любой момент хакер может создать новый билет, чей срок действия не превышает разрешенного в политике домена. Таким образом можно сохранять доступ к домену на долгое время и при этом не попадаясь под такого рода детект.
Пример детекта 4
Предлагаемый вариант:
Можно воспользоваться логами 4769 — service ticket request на DC для поиска пользователей или доменов, которые не существуют в среде [4].
В чем минус:
Нет каких-либо ограничений, чтобы создать TGT билет под существующего в домене пользователя, например, доменного администратора.
Пример детекта 5
Предлагаемый вариант:
Вооружившись Золотым билетом, злоумышленники могут запрашивать TGS для горизонтального перемещения и выполнения кода на удаленных системах. Мониторинг запросов TGS с использованием устаревшего механизма шифрования RC4 может представлять собой второй этап атаки Golden Ticket. Появление RC4 должно быть редкостью в современной сети, поскольку Windows Vista и Windows Sever 2008 и более поздние версии поддерживают шифрование AES Kerberos [5].
В чем минус:
Приводя в пример этот способ детекта, коллеги также указывают, что его все равно можно обойти: «Защитники должны иметь в виду, что если злоумышленник использует не хэш пароля NTLM, а ключ AES для создания Золотого билета, этот способ обнаружения можно обойти».
Альтернативный способ детекта: теория
Как специалистам по информационной безопасности, нам важно понять какой метод детектирования Golden Ticket действительно работает и существует ли он? Изучив примеры детекта коллег, описанные выше, и поняв, какими минусами они обладают, выдвенем свою теорию детектирования как пример надежного способа обнаружения, после чего на практике попытаемся найти ее подтверждение.
Итак, в случае легитимной ситуации при запросе, например, доступа к серверу, пользователь получает два билета: TGT и следом за ним TGS. Это видно в шагах 1-4 на схеме на Рисунке 1. Шаг 5 реализует уже доступ к серверу с помощью TGS билета.
Но при атаке Golden Ticket шаги 1 и 2 отсутствуют.
Атакующему не нужно выполнять TGT запрос, так как он формирует билет самостоятельно на собственной локальной машине, поэтому злоумышленник сразу запрашивает TGS. Дальнейшие действия будут идентичны легитимной активности.
Общую логику детектирования можно свести к следующему: так как при атаке Golden Ticket атакующий использует локально сгенерированный TGT билет, то мы можем следить за выданными KDC билетами и позволять отдавать TGS билет только в том случае, если был предъявлен TGT билет, выданный KDC ранее. Как мы помним, пользователь домена получает TGT раз в 10 часов (стандартное поведение), поэтому TGT и TGS запрос могут не выполняться сразу, и есть смысл сохранять события получения TGT, как минимум, в течение этих 10 часов для каждого пользователя.
Теоретически стоит также наблюдать за типом шифрования, которое использует билеты, так как ленивые злоумышленники в основном крадут и пользуются NT-хэшем для создания билетов. NT-хэш использует MD5 шифрование и это отображается в логах как 0x17 в поле Ticket Encryption Type. Но у атакующего есть возможность воспользоваться любым типом шифрования, включая обычно используемый AES-256, поэтому строить свое правило детектирования только на типе шифрования неправильно.
При этом существует способ обойти ситуацию, когда у нас отсутствует запрос на TGT. Он заключается, как ни странно, в самом запросе TGT билета. Выполнить успешный AS_REQ (запрос для получения TGT) можно только если мы знаем пароль пользователя.
Сразу возникает вопрос: тогда зачем нам Golden Ticket, если мы знаем пароль пользователя? На самом деле смысл есть: в TGT содержится информация о правах пользователя (Privilege Attribute Certificate или PAC), и атакующий может расшифровать билет вместе с PAC, изменить права, зашифровать обратно и применить этот билет, сделав из обычного пользователя администратора домена. Если атаку провести таким образом, то детектирование на отсутствии запроса TGT будет бесполезным. В этом случае нам нужно наблюдать не только за событиями по выпуску билетов, а еще также и за Logon (Event ID == 4624) на всех Endpoint-машинах. Дело в том, что если SID пользователя не соответствует его имени, то это выглядит как минимум подозрительно. И это видно в Logon логах, вот пример:
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-05-11T09:35:17.550325200Z" />
<EventRecordID>6588501</EventRecordID>
<Correlation ActivityID="{daf28f32-6519-0001-0391-f2da1965d801}" />
<Execution ProcessID="728" ThreadID="788" />
<Channel>Security</Channel>
<Computer>dc02.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-21-3658376699-1331227660-3084883410-500</Data>
<Data Name="TargetUserName">test</Data>
<Data Name="TargetDomainName">SEA.LAND</Data>
<Data Name="TargetLogonId">0x1e6f66</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">Kerberos</Data>
<Data Name="AuthenticationPackageName">Kerberos</Data>
<Data Name="WorkstationName">-</Data>
<Data Name="LogonGuid">{3e3b5747-5b7e-fbac-b3e2-2c6b67173d32}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">172.16.99.153</Data>
<Data Name="IpPort">46858</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
На скриншоте видно, что злоумышленник не сможет поменять имя пользователя так, чтобы пользователь подходил под SID. Ведь если он так сделает, то сработает правило на отсутствие TGT билета. Таким образом, создается замкнутый круг, на каждом этапе которого мы можем детектировать атаку:
Читатель, знающий о функции PAC Validation, задаст резонный вопрос: Почему мы просто не включим эту функцию и будем защищены от подделки PAC? По не до конца понятным причинам, PAC Validation не срабатывает при атаках Golden Ticket и Silver Ticket.
Слабое место такого подхода заключается в следующей ситуации: легитимный пользователь домена запросил TGT и использует его, при этом атакующий сгенерировал свой собственный TGT на этого же пользователя. Так как легитимному пользователю был выдан TGT и при этом не было изменения PAC, то поддельный TGT билет не попадёт под детект.
Эта ситуация показывает, что недостаточно просто смотреть на отсутствие TGT билета у пользователей: необходимо понимать какой конкретно билет был выдан KDC, а какой поддельный.
Вспомним, что при запросе TGS пользователю необходимо предоставить свой TGT билет. Он зашифрован и представляет собой лишь строку. Мы не можем посмотреть его данные полностью, но для нас это не так важно, так как для того, чтобы связать конкретные TGT и конкретные TGS билеты нужно лишь уникальное значение TGT билета. И зашифрованная строка – это как раз то, что нам необходимо. Этот шифр можно свободно просматривать в трафике запроса TGS, так как в тело этого запроса включён зашифрованный TGT. Важно напомнить, что зашифрованный TGT содержит в себе метку времени или timestamp, а также случайно сгенерированный ключ для дополнительной безопасности Session Key, что делает каждый конкретный TGT уникальным.
Если говорить про логику детектирования Golden Ticket, то здесь все довольно прозрачно: мы записываем в таблицу все TGT билеты, которые были выданы KDC. И при любом запросе TGS билета проверяем выдавал ли KDC тот TGT билет, который предоставляется.
Этот подход позволяет также детектировать изменение PAC в легитимно выданных билетах, так как если изменить только PAC и ничего более, то зашифрованная строка билета всё равно изменится и уже не пройдёт валидацию.
Ниже представлена схема, отражающая способы по возможным вариациям Golden Ticket.
Единственный момент, не покрывающий такой детект – это ситуация, при которой злоумышленник имеет на руках пароль (или ключ) доменного или локального администратора. С такой информацией атакующий сможет расшифровать TGT билет пользователя и узнать timestamp и Session Key, который был применён. После чего использовать его для генерации собственного TGT билета. Но в таких случаях злоумышленнику не нужно использовать Golden Ticket, он может напрямую запросить TGT и TGS билеты абсолютно легитимно или использовать другие методы аутентификации.
Разбираем на практике
Теперь нашу теорию нужно проверить на практике. Поэтому разберем, как предложенный нами способ детекта работает на самом деле. А именно, рассмотрим траффик, в котором видно содержание зашифрованного TGT билета при его получении от KDC и его применении для запроса TGS. Также рассмотрим почему логи Windows Event Log нам не сильно в этом помогут.
Как было сказано в разделе теории, в трафике запроса TGS мы можем увидеть зашифрованный TGT билет, который используется для запроса.
Примеры трафика из Wireshark:
На первой картинке пример ответа AS-REP, который содержит зашифрованный TGT билет пользователя;
На второй картинке мы видим шифр, который был получен в ответе на запрос.
Таким образом можно фиксировать какой TGT был применён для запроса конкретного TGS билета, что позволяет нам отслеживать использование поддельных TGT.
Если злоумышленник попробует изменить только PAC структуру, и\или содержащийся в ней SID пользователя, то билет будет изменён что так же можно увидеть в трафике.
Измененная часть билета выделена на Рисунках 8 и 9.
Попытка детектирования с помощью WinEventLog
Для детектирования атак на Windows чаще всего используют стандартные встроенные логи, или Event Logs, так как они дают хорошую информативность и просты в использовании. Давайте посмотрим что в них можно отыскать, чтобы указывало на атаку Golden Ticket.
Domain controller (DC)
Контроллеры домена (DC), как машины для выдачи Kerberos билетов, будут содержать особые логи в которых мы можем отслеживать запросы и выдачу билетов. Такие логи нам более всего интересны.
При выполнении атаки, как и в случае с легитимной активностью, нами используется AES-256. Легитимный запрос TGS_REQ на первой картинке и запрос TGS_REQ при выполнении атаки на второй. Как видно, единственное отличие в этих двух событиях заключается в поле Ticket Options. Согласно документации Microsoft, наиболее популярные значения Ticket Options:
0x40810010 - Forwardable, Renewable, Canonicalize, Renewable-ok
0x40810000 - Forwardable, Renewable, Canonicalize
0x60810010 - Forwardable, Forwarded, Renewable, Canonicalize, Renewable-ok
Можно заметить, что значение 0x40810010 является частым явлением, поэтому если основываться только на данном факте, то мы получим множество ложных срабатываний, не говоря уже о возможности изменить это значение злоумышленником.
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4769</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>14337</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-05-11T09:37:03.242947400Z" />
<EventRecordID>6588729</EventRecordID>
<Correlation />
<Execution ProcessID="728" ThreadID="920" />
<Channel>Security</Channel>
<Computer>dc02.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="TargetUserName">DC02$@SEA.LAND</Data>
<Data Name="TargetDomainName">SEA.LAND</Data>
<Data Name="ServiceName">DC01$</Data>
<Data Name="ServiceSid">S-1-5-21-3658376699-1331227660-3084883410-3101</Data>
<Data Name="TicketOptions">0x40810000</Data>
<Data Name="TicketEncryptionType">0x12</Data>
<Data Name="IpAddress">::1</Data>
<Data Name="IpPort">0</Data>
<Data Name="Status">0x0</Data>
<Data Name="LogonGuid">{dd98761a-55eb-0ae7-4028-61588c25405f}</Data>
<Data Name="TransmittedServices">-</Data>
</EventData>
</Event>
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4769</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>14337</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-05-11T09:37:14.231534000Z" />
<EventRecordID>6588746</EventRecordID>
<Correlation />
<Execution ProcessID="728" ThreadID="3560" />
<Channel>Security</Channel>
<Computer>dc02.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="TargetUserName">test@SEA.LAND</Data>
<Data Name="TargetDomainName">SEA.LAND</Data>
<Data Name="ServiceName">ARM01$</Data>
<Data Name="ServiceSid">S-1-5-21-3658376699-1331227660-3084883410-1134</Data>
<Data Name="TicketOptions">0x40810010</Data>
<Data Name="TicketEncryptionType">0x12</Data>
<Data Name="IpAddress">::ffff:172.16.99.153</Data>
<Data Name="IpPort">43594</Data>
<Data Name="Status">0x0</Data>
<Data Name="LogonGuid">{1f7ca762-3eef-0192-15e3-f07c9680d2a8}</Data>
<Data Name="TransmittedServices">-</Data>
</EventData>
</Event>
Endpoint
Если рассматривать ситуацию с конечными устройствами, то события, происходящие с ними для нас не столь интересны. Нам доступны только события, отражающие вход пользователя, которые практически идентичны при атаке и при легитимном применении билетов.
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-09-07T13:46:33.125574300Z" />
<EventRecordID>3370723</EventRecordID>
<Correlation ActivityID="{26166827-bc72-0001-2e69-162672bcd801}" />
<Execution ProcessID="624" ThreadID="12064" />
<Channel>Security</Channel>
<Computer>vs01.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-21-3658376699-1331227660-3084883410-1107</Data>
<Data Name="TargetUserName">kchernyh</Data>
<Data Name="TargetDomainName">SEA.LAND</Data>
<Data Name="TargetLogonId">0x185bdae8</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">Kerberos</Data>
<Data Name="AuthenticationPackageName">Kerberos</Data>
<Data Name="WorkstationName">-</Data>
<Data Name="LogonGuid">{77f17c0c-1ae7-f52b-a937-e80f093d5d85}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">10.150.161.10</Data>
<Data Name="IpPort">40840</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-09-07T13:47:36.067513800Z" />
<EventRecordID>3370742</EventRecordID>
<Correlation ActivityID="{26166827-bc72-0001-2e69-162672bcd801}" />
<Execution ProcessID="624" ThreadID="3508" />
<Channel>Security</Channel>
<Computer>vs01.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-21-3658376699-1331227660-3084883410-1107</Data>
<Data Name="TargetUserName">kchernyh</Data>
<Data Name="TargetDomainName">SEA.LAND</Data>
<Data Name="TargetLogonId">0x185c6c75</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">Kerberos</Data>
<Data Name="AuthenticationPackageName">Kerberos</Data>
<Data Name="WorkstationName">-</Data>
<Data Name="LogonGuid">{f0f15c65-6158-5674-8da2-7b159ac7962e}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">10.150.161.10</Data>
<Data Name="IpPort">51870</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
У лога 4624 (Logon) существует поле Logon GUID, которое коррелируется с Logon GUID в логе 4769 (Kerberos Service Ticket Operations). Эта корреляция может указывать на выдачу и применение одного и того же конкретного билета, что звучит очень полезно в нашем случае, но это касается только TGS билетов. Поддельные же TGT билеты, на которые и направлена атака, не содержат в себе поля Logon GUID и не могут быть ни с чем скоррелированны, что делает это поле бесполезным для нас, так как злоумышленник в любом сценарии атаки будет запрашивать легитимный TGS билет.
События с конечных устройств могут быть полезными, если атакующий использует TGT пользователя, к которому он знает пароль. В таком случае выполняется легитимный TGT запрос. Поскольку атакующий стремиться получить административные права, изменяя при этом PAC, то мы можем это увидеть в примере события: Security ID, который отвечает за права пользователя, не соответствует имени пользователя. Это отличный индикатор применения Golden Ticket с изменением прав существующего пользователя.
XML версия лога
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2022-05-11T10:10:45.698712200Z" />
<EventRecordID>88901541</EventRecordID>
<Correlation ActivityID="{AFCEFD84-651D-0001-8EFD-CEAF1D65D801}" />
<Execution ProcessID="668" ThreadID="724" />
<Channel>Security</Channel>
<Computer>arm01.sea.land</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-21-3658376699-1331227660-3084883410-500</Data>
<Data Name="TargetUserName">simpleuser</Data>
<Data Name="TargetDomainName">SEA</Data>
<Data Name="TargetLogonId">0x15f26c</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">Kerberos</Data>
<Data Name="AuthenticationPackageName">Kerberos</Data>
<Data Name="WorkstationName">-</Data>
<Data Name="LogonGuid">{1038D45C-DCEA-D52C-766A-ECC5A96D2DF7}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">-</Data>
<Data Name="KeyLength">0</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">172.16.99.153</Data>
<Data Name="IpPort">34966</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
Ложка дегтя в событиях
Когда атакующий изменяет SID пользователя в структуре PAC от TGT билета, повышая тем самым свои привилегии до административных, нам важно наблюдать соответствие имени пользователя в полях Security ID и Account Name. Однако, это может не всегда корректно сработать, потому что Windows (если эта машина не является DC) кеширует пару SID/имя пользователя при его аутентификации без проверки принадлежности SID. Таким образом, мы можем получать примеры подобных событий:
Аутентификация пользователя simpleuser с SID администратора
Аутентификация пользователя kchernyh с SID администратора
Аутентификация администратора
SID администратора всегда ассоциируется с пользователем simpleuser из-за того, что атакующий зашёл под этим пользователем с административными правами. Windows "запомнила" эту пару. Кэш очищается при перезагрузке машины. Поэтому здесь нужно обратить внимание на 2 важные вещи:
Такое происходит только на конечных устройствах. На контроллерах домена все работает корректно.
XML версия лога показывает истинный SID пользователя без преобразования его в имя, поэтому настоятельно рекомендуется собирать с конечных машин XML логи и сравнивая их уже впоследствии.
Подведем итог
Для эффективной защиты от данной атаки следует использовать трафик в качестве сборщика информации, а также реализовать таблицу TGT билетов, с помощью которой можно отслеживать как выпущенные TGT билеты, так и попытки использовать нелегитимные TGT билеты. Такой подход обеспечит детектирование как полностью поддельных билетов, так и частично изменённых билетов, например, в структуре PAC.
Proof of Сoncept (PoC)
Ниже представлен скрипт, ориентированный на трафик, как основу для детектирования. Он может применяться как детект в реальном времени или же для статических .pcap файлов.
import subprocess
import json
import threading
table = []
# Slicing the cipher just for memory economy
sliceCipher = 10
def loadPackets ():
return json.loads(subprocess.check_output(['tshark', '-r', 'golden-ticket.pcap', '-T', 'json', '-x']))
def writeToTable (username, cipher):
print ("I write to table:", username, cipher)
table.append({'username': username, 'cipher': cipher})
def checkTGS (username, cipher):
print("I check table:", username, cipher)
for record in table:
if record['username'] == username and record['cipher'] == cipher:
return True
def main ():
packets = loadPackets()
tgs_cipher = ''
for packet in packets:
packet = packet['_source']['layers']
if 'kerberos' in packet:
kerberos_ticket_name = list(packet['kerberos'].keys())[2]
packet = packet['kerberos'][kerberos_ticket_name]
if 'as_rep' in kerberos_ticket_name:
username = packet['kerberos.cname_element']['kerberos.cname_string_tree']['kerberos.CNameString']
cipher = packet['kerberos.ticket_element']['kerberos.enc_part_element']['kerberos.cipher_raw'][0][0:sliceCipher]
# Writing username and the cipher to the table
writeToTable(username, cipher)
if 'tgs_req' in kerberos_ticket_name:
tgs_cipher = packet['kerberos.padata_tree']['kerberos.PA_DATA_element']['kerberos.padata_type_tree']\
['kerberos.padata_value_tree']['kerberos.ap_req_element']['kerberos.ticket_element']['kerberos.enc_part_element']\
['kerberos.cipher_raw'][0][0:sliceCipher]
if 'tgs_rep' in kerberos_ticket_name:
if checkTGS(packet['kerberos.cname_element']['kerberos.cname_string_tree']['kerberos.CNameString'], tgs_cipher):
print('No attack')
else:
print('Golden Ticket Attack')
def printit():
threading.Timer(5.0, printit).start()
main()
printit()
Один из вариантов запуска скрипта:
Запустить сбор трафика в .pcap файл (нами использовался: tshark -i tun0 -w golden-ticket.pcap);
Указать в скрипте путь до .pcap файла для чтения и конвертации в JSON (я опять же использовал tshark);
Запустить скрипт.
Возможные утилиты для практики:
Имея на руках секретный ключ от сервисной учетной записи KBRGT можно в рамках домашней лаборатории попрактиковаться со следующими инструментами:
Возможные варианты реагирования:
Если стало известно о краже ключа учётной записи KRBTGT, то существует процедура по его изменению. Только она чуть сложнее в организационном плане, чем для любого другого пользователя в домене. Важно сменить пароль дважды (так как старый пароль сохраняется в истории паролей и будет считаться валидным) на всех контроллерах домена. Microsoft предоставляет Powershell скрипт специально для этого и рекомендует менять пароль KBRGT каждые 180 дней.
Теперь вы знаете еще один успешный практический пример детекта Золотого билета. Надеемся, что предложенный нами способ окажется вам полезным. Спасибо всем за внимание! Пишите комментарии, задавайте вопросы – будем рады! :-)
GritsanY
Статья точно не перевод? Читается немного натужно, как прямая калька с английских оборотов.
HappyGroundhog
Статья абсолютно точно не перевод, но при написании статьи было проделано очень много аналитической работы с различными материалами, которые в основном доступны исключительно на английском. Это накладывает определённый отпечаток на стиль повествования.