Один из наиболее сложных, но в то же время эффективных методов получения неавторизованного доступа к ресурсам внутри корпоративной сети — это атака с использованием поддельных сертификатов. Суть ее заключается в создании злоумышленником таких сертификатов, которые будут приняты Центром распространения ключей (Key Distribution Center, KDC) и обеспечат доступ к ресурсам внутри сети атакуемой компании. Примером такой атаки является техника Shadow Credentials, которая позволяет авторизоваться под учетной записью пользователя, если атакующий может изменить атрибут msDS-KeyCredentialLink жертвы и добавить к нему сертификат для авторизации. Такие атаки трудно обнаружить, поскольку вместо кражи учетных данных злоумышленники работают с легитимными механизмами Active directory (AD) и недостатками конфигурации.
Тем не менее противостоять атакам с использованием поддельных сертификатов можно (и нужно). Я проанализировал практический опыт нашего сервиса MDR, после чего выявил несколько признаков присутствия таких атак внутри сети и разработал Proof-of-Concept утилиты, способной находить артефакты в AD, а также несколько правил детектирующей логики, которые можно добавить в SIEM. Но сначала несколько слов о том, в чем кроется неочевидный нюанс с аутентификацией Kerberos с использованием сертификатов.
Аутентификация Kerberos в AD и нюансы ее реализации
В современных корпоративных сетях, основанных на Active Directory, управление ресурсами происходит благодаря протоколу Kerberos. Пользователь может получить доступ к какому-либо сервису (объекту) внутри сети, только если он может предоставить этому объекту билет, выданный Центром распространения ключей (Key Distribution Center, KDC) («Msg E» на рисунке ниже). Отвечающий за выдачу сервисных билетов компонент KDC называется «Сервер выдачи билетов» (Ticket Granting Server, TGS). При этом пользователь может получить TGS-билет от KDC, только если у него есть «билет для получения билетов» (Ticket Granting Ticket, TGT) («Msg B» на рисунке ниже). По сути, TGT-билет является доказательством успешного прохождения пользователем аутентификации, как правило, по паролю.
Однако существует способ получить TGT-билет без знания пароля — по сертификату. Для этого нужно, чтобы KDC доверял предоставленному сертификату, а сертификат относился к субъекту, который запрашивает TGT-билет. Эта часть протокола Kerberos называется Public Key Cryptography for Initial Authentication (PKINIT), и с ее помощью достаточно просто организовать аутентификацию, если в корпоративной сети существует удостоверяющий центр (Certificate Authority), который выдает сертификаты для пользователей домена. Однако есть и альтернативный способ.
Например, для того чтобы воспользоваться возможностями Microsoft Нello for Business, такими как авторизация с использованием PIN-кода или распознавания лица, необходимо, чтобы устройство, с которого осуществляется вход, имело в AD свой сертификат и KDC мог выписать TGT-билет по этому сертификату. Однако далеко не во всех сетях с Active Directory есть удостоверяющий центр. Поэтому для объектов AD был придуман атрибут msDS-KeyCredentialLink, в который можно записать сертификат. При выдаче TGT-билета служба KDC будет доверять этому сертификату. И это действительно хорошее решение, расширяющее возможности Microsoft Active Directory.
Однако исходя из описанной выше логики, тот субъект, который может контролировать запись атрибута msDS-KeyCredentialLinkу какого-либо объекта, сможет и получить билет за этот объект. В этом и заключается проблема.
Как происходит атака
Проиллюстрируем один из возможных сценариев атаки:
- Субъект logan_howard, обладая правами на запись любого атрибута в домене Active Directory, записывает публичный ключ в атрибут msDS-KeyCredentialLink для объекта контроллера домена (ad-gam$). Используется инструментарий Whisker.
- Субъект получает TGT-билет (используется инструментарий Rubeus), выписанный на контроллер домена.
- Предъявив этот TGT, субъект получает TGS-билет для синхронизации парольной информации в домене (MS-DRSR: Directory Replication Service (DRS) Remote Protocol).
- От имени субъекта злоумышленник «синхронизирует» хэш от учетной записи администратора домена (Administrator), чтобы выдать себя за него для получения доступа к данным и горизонтального перемещения внутри корпоративной сети. Эта атака называется DCSync, для нее используется mimikatz.
Где следует искать какие-либо артефакты?
Давайте сфокусируем внимание не на способе, которым можно заставить KDC доверять тому или иному сертификату, в том числе украденному или поддельному, а на том, что происходит в момент выдачи TGT-билета. В этот момент на контроллере домена происходит событие 4768: запрошен билет проверки подлинности Kerberos (TGT). Это событие может содержать артефакты от сертификата, по которому и осуществлялась аутентификация, — три поля: CertIssuerName, CertSerialNumber и CertThumbprint. Собственно, этими полями мы и ограничимся.
Каким инструментарием следует воспользоваться?
Для простоты и удобства мы сразу же будем обрабатывать все события в интерфейсе Kibana кластера ELK. Действительно, по умолчанию Logstash умеет преобразовывать битовые поля события 4768 в массив значений, характерных для билета из списка. Кроме того, поиск пройдет значительно быстрее и приятнее. Я рекомендую использовать для лаборатории удобный набор Docker-конфигураций для быстрого старта ELK. И официальную инструкцию по настройке WinLogBeat.
Что мы можем сказать об этих событиях?
На тестовом стенде мы сгенерировали несколько событий запроса TGT по поддельному сертификату, который сгенерировали с помощью Whisker. Так эти события выглядят в тестовом окружении:
В рамках сервиса MDR мы наблюдаем несколько сотен тысяч событий запросов билета по сертификату в неделю, это достаточно широкая выборка, и поэтому на основании этих событий мы можем выявить некоторые закономерности:
- Значительная часть событий — это запрос билета по сертификату на службу Microsoft Azure Active Directory (строчка «Azure» в агрегации на скриншоте ниже). Данные события нас не интересуют, их легко отфильтровать с помощью регулярного выражения по значению поля CertIssuerName в интерфейсе Kibana.
CertIssuerName.raw:/S\-1\-(5\-21|12\-1)\-([0-9]{8,10}\-){3}[0-9]{4,10}\/[a-f0-9]{8}\-([a-f0-9]{4}\-){3}[a-f0-9]{12}\/login\.windows\.net\/[a-f0-9]{8}\-([a-f0-9]{4}\-){3}[a-f0-9]{12}.*/ |
- Также много событий для сертификатов, которые использует Microsoft Hello For Business (строчка «Hello4B self gen»). В этом случае данные о сертификате записаны в атрибут msDS-KeyCredentialLink, а ключ программно сгенерирован (NCRYPT_IMPL_SOFTWARE_FLAG). Для них характерны имена, начинающиеся с «CN=», и двузначный серийный номер, как правило, 01.
CertIssuerName.raw:CN=* AND CertSerialNumber.raw:01 |
- Если компьютер имеет ключ, записанный в Trusted Platform Module (строчка «TPM enrolled»), то сертификат, который использует этот ключ, также может быть описан регулярными выражениями и нас не интересует.
CertSerialNumber.raw:/[a-f0-9]{32}/ AND CertThumbprint.raw:/[a-f0-9]{40}/ |
- Но, наверное, самый популярный случай — это использование сертификатов, которые выписаны Microsoft Сertificate Authority (строчка «Windows server CS role issued»). Эта служба может быть включена в компьютере под управлением серверной версии Microsoft Windows. Тут, наверное, следует заметить, что если вы самостоятельно осуществляете мониторинг вашей локальный инфраструктуры и не являетесь MSSP-провайдером, то вам будет значительно проще отфильтровать этот случай просто по имени CertIssuerName — по названию вашего CA-сервера (скорее всего, единственного на каждый домен в лесу). И действительно, даже большие корпоративные сети имеют достаточно небольшое количество CA, которые могут выдавать сертификаты. Но даже если вы — провайдер услуг безопасности, то для вас все равно не представит большого труда выяснить имена всех серверов клиентских PKI для того, чтобы их отфильтровывать. Я же хочу показать некоторую закономерность в других полях.
CertSerialNumber.raw:/[a-f0-9]{38}/ AND CertThumbprint.raw:/[a-f0-9]{40}/ |
- Также могут встречаться сторонние реализации PKI, сертификатам которых доверяют серверы Kerberos при выдаче билетов. Например, у нас в мониторинге встречается специализированное ПО от фирмы Lanaco (не более десяти запросов за 30 дней). Мы его также можем отфильтровать.
Давайте посмотрим на реальных данных, какие запросы мы можем отфильтровать. Для этого можно построить следующую агрегацию, используя описанные выше регулярные выражения:
Исследуем код Whisker
Как я уже упоминал, в нашем примере сертификат был сгенерирован в самой утилите Whisker c параметрами по умолчанию. Сама процедура генерации самоподписанного сертификата описана тут.
Whisker, как мы видим, пытается выдавать свои сертификаты за сертификаты от Windows Hello For Business (в случае с программным созданием ключевой пары). Однако в оригинальных сертификатах (когда ПК под управлением Windows самостоятельно сгенерировал сертификат для использования этого функционала) есть ошибка — в поле CertIssuerName записана нотация DN (от англ. Distinguished Name) в формате «CN=…». Инструментарий атакующих лишен этой ошибки — это и подозрительно. Можете сравнить вторую и третью строку с данными, полученными на тестовом стенде, но в продуктовой системе MDR (также см. ниже).
Мы можем прямо в Kibana добавить painless-скрипт, способный отыскать все события 4768, в которых CertIssuerName регистронезависимо совпадает с TargetAccountName.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "query": { "bool": { "filter": { "script": { "script": { "lang": "painless", "source": "doc['CertIssuerName.raw'].value.equals(doc['TargetAccountName.raw'].value.toLowerCase())" } } } } } } |
Таких событий десять, и все они относятся к использованию утилиты Whisker.
Исследуем поля с флагами билета
Теперь рассмотрим поле «winlog.event_data.TicketOptionsDescription» в событиях с тестового стенда за произвольный интервал времени, где встречается как поддельный, так и легитимный запрос TGT.
В глаза бросается отсутствие флага Name-canonicalize, который играет важную роль в инфраструктуре Kerberos. Дело в том, что у службы или учетной записи может быть несколько основных имен. Например, если хост известен под несколькими именами, службы на его основе могут иметь несколько имен Service Principal Name (SPN). Чтобы клиент не нуждался в запросе билета для каждого из имен, KDC может предоставить ему информацию о сопоставлении в процессе получения учетных данных. Этот функционал и запрашивается при включении флага Name-canonicalize. Если установлена опция «канонизировать», то KDC может в ответе и TGT-билете изменить имена и SPN как клиента, так и сервера. Но в нашем случае этого флага нет, и это подозрительно. Найдем все билеты без этого флага, но запрошенные с помощью PKINIT (по сертификату). Запрос сделаем по продуктовым данным Kaspersky MDR.
В результате мы можем видеть активность (за последние 30 дней) от Whisker + Rubeus на нашем стенде (хост AD-Gam) и работу моего коллеги (остальное) по тестированию группы уязвимостей слабых настроек AD CS, которые объединили под общим названием ADCS ESC или Certified Pre-Owned. Также есть одно отфильтрованное по имени сертификата ложное срабатывание и один инцидент, отправленный клиенту. Это неплохая конверсия.
Давайте рассмотрим на примере Rubeus, почему при запросе билета не выставляется флаг Name-canonicalize.
Да, действительно, инструментарий Rubeus нарочно не выставляет этот флаг. Более того, то же самое делает Impacket — де-факто стандартный инструментарий для работы с Kerberos (и не только) для специалистов по анализу защищенности. Этим и объясняется то, что в ходе поиска билетов без флага мы также нашли и работу моего коллеги, который тестировал ESC-техники, — используемый им инструментарий базируется на Impacket. Такого рода утилит, благодаря простоте кода и популярности языка, очень много.
А что же сам атрибут msDS-KeyCredentialLink?
Мы можем сравнить два атрибута: один легитимно выставленный в процессе настройки Hello For Business, а другой — установленный Whisker. И разница между ними есть. Занимаясь сравнением этих атрибутов, я и написал утилиту, которая позволит вам найти артефакты от нелегитимной установки атрибута, например в результате использования Whisker.
Вы можете самостоятельно скачать и использовать эту утилиту в среде разработки, во время отладки попробуйте найти и сравнить ключевые отличия в «злом» и «добром» атрибуте.
На что нужно обратить внимание:
- Существует ли DeviceId у атрибута msDS-KeyCredentialLink (формат GUID). Если да, и при этом объекта с таким идентификатором нет в домене, — это подозрительно. Если же объект есть и при этом относится к коннектору Azure AD, то это похоже на легитимный случай.
- Поле Flags не содержит MFANotUsed. Как правило, в легитимном случае содержит.
- KeyMaterial имеет длину, отличную от 270 байт, — именно такие артефакты оставляет Whisker.
- Почти идентичные KeyApproximateLastLogonTimeStamp и Однако это менее надежный показатель, его лучше не использовать.
Резюмируем
Описанные выше атаки сравнительно эффективны, но их можно обнаруживать в момент использования поддельного сертификата. В этом специалисту по информационной безопасности помогают знание своей инфраструктуры (в идеале — составление списка всех активных ключей) и мониторинг. При этом понимание некоторых общих шаблонов и артефактов атак с использованием поддельного сертификата может оказать значительную поддержку, а моя утилита упростит процесс поиска.
Детектирование аномалий при запросе TGT-билета по сертификату