
Атака внутреннего монолога: получение NTLM-хэшей без обращения к LSASS
Mimikatz, разработанный Бенджамином Делпи (@gentilkiwi), является широко известным инструментом для постэксплуатации, позволяющим злоумышленникам извлекать из памяти пароли в открытом виде, NTLM-хеши и билеты Kerberos, а также выполнять такие атаки, как pass-the-hash, pass-the-ticket или создавать golden ticket. Бесспорно, основное применение Mimikatz — это получение учётных данных пользователя из памяти процесса LSASS для использования в последующем латеральном перемещении.
Недавно Microsoft внедрила Credential Guard в Windows 10 Enterprise и Windows Server 2016, который использует виртуализацию для изоляции секретов и очень эффективно предотвращает извлечение хешей Mimikatz напрямую из памяти. Кроме того, Mimikatz стал главной целью большинства средств защиты конечных точек, которые активно пытаются его обнаружить и заблокировать. Хотя эти попытки обречены на провал, они становятся всё более досадной помехой.
NetNTLM — это протокол «вызов-ответ» Windows, используемый в основном там, где Kerberos не поддерживается. В NetNTLM сервер отправляет клиенту случайное 8-байтовое значение (nonce) в качестве вызова, а клиент вычисляет ответ, обрабатывая вызов с помощью NTLM-хеша в качестве ключа, который является MD4-хешем пароля пользователя. Существует две версии протокола аутентификации NetNTLM, и обе уязвимы к определённым атакам. Естественно, версия 1 значительно слабее версии 2, поэтому начиная с Windows Vista/2008 NetNTLM версии 1 по умолчанию отключена.
Поскольку NTLM-хеш является ключом для вычисления ответа, злоумышленнику не обязательно получать пароль жертвы в открытом виде для аутентификации; следовательно, извлечение хеша из памяти LSASS с помощью Mimikatz практически эквивалентно краже пароля. Крис Хаммель опубликовал статью, описывающую эту технику в 2009 году, и назвал её «Pass the Hash» [https://www.sans.org/reading-room/whitepapers/testing/crack-pass-hash-33219].
На Defcon 2012 Мокси Марлинспайк и Дэвид Халтон представили атаку «Разделяй и властвуй» против NetNTLMv1 [https://www.youtube.com/watch?v=sIidzPntdCM]. В NetNTLMv1 клиент получает 8-байтовый вызов и вычисляет ответ, шифруя его три раза с помощью DES, используя различные части NTLM-хеша в качестве ключа. Эффективная длина ключа DES составляет 56 бит, то есть 7 байт, тогда как NTLM-хеш имеет размер 16 байт. NetNTLMv1 сначала шифрует вызов, используя первые 7 байт NTLM-хеша в качестве ключа, затем шифрует вызов, используя следующие 7 байт NTLM-хеша в качестве ключа, и, наконец, шифрует вызов, используя последние 2 байта NTLM-хеша, дополненные нулями, в качестве ключа. Фактически это означает, что для получения NTLM-хеша по заданному вызову и ответу NetNTLMv1 злоумышленник должен взломать два 56-битных ключа DES, что экспоненциально проще, чем взлом одного 128-битного ключа. Мокси и Халтон разработали специальное оборудование для этой задачи и смогли перебрать всё пространство ключей DES менее чем за 24 часа, что гарантирует успешное получение NTLM-хеша за разумное время. Обратите внимание: в отличие от атак по словарю или полного перебора пароля, которые могут не дать результата, данная атака гарантирует успешное получение NTLM-хеша.
Как показано на ToorCon (https://crack.sh), возможно создать полную радужную таблицу для всех возможных ответов NetNTLMv1 на выбранный вызов, например 0x1122334455667788, что позволяет взломать NTLM-хеш для заданного ответа за несколько минут. Это означает, что перехват ответа NetNTLMv1 на выбранный вызов может быть почти мгновенно преобразован в соответствующий NTLM-хеш, что практически эквивалентно получению пароля благодаря атаке Pass the Hash.
Mimikatz обычно выполняется после того, как злоумышленник получил повышенный доступ к целевому хосту. На этом этапе злоумышленник может также изменить ключи реестра, такие как LMCompatibilityLevel, который определяет, должен ли хост согласовывать NetNTLMv1 или NetNTLMv2. Злоумышленник может изменить значение на 0, 1 или 2, что включает NetNTLMv1 на стороне клиента, а затем попытаться аутентифицироваться на подставном SMB-сервере, который перехватит ответ клиента, как описано в блог-посте Optiv [https://www.optiv.com/blog/post-exploitation-using-netntlm-downgrade-attacks].
Есть ещё два параметра, которые могут помешать жертве согласовать ответ NetNTLMv1:
В защищённых средах, где Mimikatz не должен выполняться, злоумышленник может провести атаку Internal Monologue, при которой он вызывает локальный вызов процедуры к пакету аутентификации NTLM (MSV1_0) из пользовательского приложения через SSPI для вычисления ответа NetNTLM в контексте вошедшего пользователя после выполнения расширенного понижения версии NetNTLM.
Поток атаки Internal Monologue описан ниже:
Недавно я повторно протестировал Internal Monologue в средах с включённым Credential Guard и получил отрицательные результаты. Я не уверен, работал ли Credential Guard неправильно в моей тестовой среде во время первоначальных тестов, или с тех пор что-то изменилось. Я обновил реализацию, чтобы динамически получать серверный токен из AcceptSecurityContext и изменять его для обхода ловушки локальной аутентификации, чтобы в случае неудачи NetNTLMv1 без расширенной безопасности сеанса можно было перехватить хотя бы вызов-ответ NetNTLMv2.
Атака Internal Monologue, возможно, более скрытна, чем запуск Mimikatz, поскольку нет необходимости внедрять код или сбрасывать память из/в защищённый процесс. Поскольку ответ NetNTLMv1 вызывается путём локального взаимодействия с NTLM SSP, сетевой трафик не генерируется, а выбранный вызов не является легко обнаруживаемым. В журналах не регистрируется событие успешной аутентификации NTLM. Изменения в реестре для понижения версии NetNTLM, а также кража токенов/олицетворение других пользователей могут вызвать срабатывание индикаторов.
Этот инструмент является доказательством концепции, реализующим атаку Internal Monologue на C#. Перенос кода в PowerShell может заменить одни события журнала в цепочке аудита на другие. Код PoC далёк от совершенства. Приветствуются положительный вклад и улучшения.
Элад Шамир из The Missing Link Security