Привет, Хабр! В предыдущей статье мы с вами изучили логику работы протокола Netlogon и выяснили, в чем заключается возможность эксплуатации уязвимости Zerologon, приводящей к смене пароля компьютерной учетной записи контроллера домена.
В этой части я разберу инструменты для проведения атаки и их кодовую базу и выясню, какие источники логов будут наиболее полезны для построения возможного детекта, а затем предложу возможные варианты обнаружения эксплуатации данной уязвимости.
Предлагаю начать с популярного инструмента - Mimikatz.
Инструмент Mimikatz
Первым проанализированным инструментом, посредством которого можно произвести эксплуатацию уязвимости является mimikatz. Пример выполнения атаки с его помощью выглядит следующим образом:
### Проверка уязвимости контроллера домена
lsadump::zerologon /target:<FQDN> /account:<user>
### Параметры
- /account: целевой DC SamAccountName
- /target: полное доменное имя целевого контроллера домена
- /exploit: проэксплуатировать уязвимость
- /null: нулевая аутентификация
- /ntlm: использовать аутентификацию NTLM, вместо Kerberos
- /type: тип безопасного канала
### Эксплуатация уязвимости
lsadump::zerologon /target:<FQDN> /account:<user> /exploit
Анализ вывода mimikatz
Ниже представлен пример вывода команды модуля Zerologon инструмента Mimikatz.
Разобрав его поподробней, в окне вывода мы видим:
Цель;
Учетную запись, а также пароль, который хотим сбросить;
Режим, в котором запускаем эксплоит (в данном случае просто проверка на уязвимость);
Ответ от сервера, говорящий о том, что сервер уязвим.
На рисунке 2 представлено уже применение эксплойта, где можно увидеть:
Запрос от клиента NetrServerAuthenticate2 из 8 нулевых байт и ответ от сервера, который говорит нам, что сервер уязвим;
Запрос от клиента NetrServerPasswordSet2 также из 8 нулевых байт на установку пустого пароля и ответ от сервера, что пароль установлен.
Далее мы видим применение эксплойта на пропатченном сервере (рисунок 3), где отображены неуспешные попытки аутентификации и ответ, что сервер неуязвим.
Теперь у нас есть возможность узнать, что происходило на уровне сети при эксплуатации Mimikatz.
Сетевой трафик Mimikatz
Разбирая сетевой трафик, можно увидеть многократно повторяющиеся вызовы методов NetrServerReqChallenge и NetrServerAuthenticate2.
На рисунке 4 показано, что отправляется ClientChallenge, состоящий из нулей, а также имя компьютера, являющегося клиентом - в данном случае это mimikatz (это прописано в коде и можно его менять).
Ниже представлен трафик в начале атаки (рисунок 5), но в этом варианте используется шифрование.
В трафике, показанном на рисунке 6, мы можем увидеть, какой Challenge посылает в ответ сервер.
Затем в вызове NetrServerAuthenticate отправляется ClientChallenge с NegotiateFlag, равным 0*212fffff
.
На рисунке 8 видно, какой ответ посылает Server в случае неуспешной попытки NetrServerAuthenticate2 .
Далее показан Server Credential, сформированный на основе Server Challenge и SessionKey, который отсылает сервер как ответ в случае, если у него получилось вычислить на своей стороне ClientCredential. То есть пытается подобрать такой SessionKey, чтобы в результате вычисленные у себя данные совпадали с отправленным клиентом ClientCredential.
Как говорилось ранее, в Mimikatz можно только посмотреть наличие уязвимости Zerologon на контроллере домена. В ходе многочисленных попыток, получая ненулевой ServerCredential от сервера, Mimikatz выведет на панели, что контроллер уязвим.
Конечным шагом выполнения атаки является сброс пароля (установка пустого пароля) компьютерной уз контроллера домена с помощью метода NetrServerPasswordSet2 (рисунок 10).
Рассмотрев сетевой трафик при эксплуатации Zerologon Mimikatz, мы делаем вывод, что распознать эксплуатацию данной уязвимости можно по многократно повторяющимся методам NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate2 (Opnum 15) в трафике от единственного источника за промежуток времени в несколько секунд.
Для лучшего понимания работы эксплойта в Mimikatz далее рассмотрим его кодовую базу.
Разбор кодовой базы mimikatz
Код для реализации атаки Zerologon посредством Mimikatz находится в файле kuhl_m_lsadump.c, а последовательность действий реализована в функции kuhl_m_lsadump_zerologon.
Алгоритм работы макросов и функций в коде выглядит следующим образом:
Все начинается с создания привязки к службе Netlogon на целевой машине с помощью функции kull_m_rpc_createBinding. Для разрешения дескриптора привязки к конкретной службе используется RpcEpResolveBinding. После этого выполняется встроенный макрос RpcTryExcept;
В коде Mimikatz макрос RpcTryExcept используется для обработки исключений, которые могут создаваться функциями NetrServerReqChallenge, NetrServerAuthenticate2 и NetrServerPasswordSet2. Применение этого макроса обеспечивает обработку исключений, вызванных во время выполнения атаки, позволяя при необходимости продолжить выполнение. Это дает возможность эксплойту быть более устойчивым к возникшим во время выполнения проблемам.
После того, как привязка выполнена внутри макроса используется функция NetrServerReqChallenge для запроса вызова с сервера. Эта функция, как уже говорилось ранее, применяется для инициации процесса аутентификации и является первым шагом в протоколе MS-NRPC. Далее используется функция NetrServerAuthenticate2 для отправки запроса аутентификации на сервер. При отправке запроса NetrServerAuthenticate2 можно увидеть, что используется флаг, 0x212fffff
, который можно изменить.
Если запрос аутентификации выполнен успешно, применятся функция NetrServerPasswordSet2 для установки пароля указанной учетной записи и это является последним шагом в эксплуатации уязвимости.
В функции kuhl_m_lsadump_zerlogon присутствует bExploit — логическая переменная, которая используется для определения того, должна ли функция пытаться применять уязвимость Zerologon или просто обнаруживать ее. Значение bExploit определяется аргументами командной строки, переданными функции.
Перейдем к следующему инструменту.
CVE-2020-1472-Exploit
Еще одним инструментом, работу которого я разобрала, будет эксплойт CVE-2020-1472 , опубликованный исследователем Paolo Stagno. Пример выполнения атаки с его помощью представлен ниже:
python3 CVE-2020-1472-exploit.py -n <NETBIOS DC name> -t <ip address>
Рассмотрим подробнее вывод команды.
Анализ вывода exploit
Ниже представлен вывод терминала при эксплуатации уязвимости через эксплойт:
Здесь мы увидим, что при выполнении эксплойта можно также выбрать, устанавливать ли пустой пароль (то есть эксплуатировать ли уязвимость) или прекратить выполнение эксплойта.
А дальше показан вывод терминала при попытке эксплуатации уязвимости на пропатченном контроллере домена (рисунок 12):
Теперь давайте проанализируем сетевой трафик, возможно мы найдем некоторые различия в поведении эксплойтов у Mimikatz и CVE-2020-1472-Exploit .
Сетевой трафик Exploit CVE-2020-1472
В трафике эксплойта видно, что каждый раз перед запросами NetrServerReqChallenge и NetrServerAuthenticate3 вызывается EPM. В Mimikatz он вызывается единожды, а затем уже массово идут вызовы NetrServerReqChallenge и NetrServerAuthenticate2.
В остальном картина почти такая же: клиент, посредством уже метода NetrServerAuthenticate3, посылает нулевой ClientChallenge, а сервер ему отвечает ServerCallenge. Затем клиент отправляет пустой ClientCredential, а сервер, в свою очередь, пытается "проверить" эти данные и, в конце-концов, вычисляя подходящий SessionKey ( рисунок 14), направляет ServerCredential в ответ.
Завершающим этапом является установка пустого пароля для машинной уз контроллера домена.
Очевидно, после разбора трафика видны некоторые отличия в эксплуатации уязвимости через Mimikatz и эксплойт. Но предлагаю заглянуть в кодовую базу и подтвердить увиденное.
Разбор кодовой базы эксплойт
Код для реализации атаки Zerologon посредством эксплойта находится в файле cve-2020-1472-exploit.py. В нем можно наблюдать использование следующих функций и библиотек:
impacket.dcerpc.v5 import nrpc, epm — библиотека от Impacket для работы с протоколом DCE/RPC и, в частности, с удаленным протоколом Netlogon и сопоставителем конечных точек;
impacket.dcerpc.v5 import transport — библиотека от Impacket для работы с транспортным уровнем протокола DCE/RPC;
MAX_ATTEMPTS— глобальная переменная, задающая максимальное количество попыток выполнения перебора (в данном случае 2000).
Затем можно видеть main — основную функцию скрипта, которую настраивает анализатор аргументов командной строки, устанавливает переменные dc_name и dc_ip и вызывает функцию Perform_attack() с соответствующими аргументами.
После чего следует функция try_zero_authenticate(dc_handle, dc_ip, target_computer), вызываемая внутри функции Perform_attack и выполняющая попытки аутентификации на контроллере домена. Она при помощи библиотек impacket совершает отправку восьми нулевых байт, а также использует NegotiateFlag (его можно изменить) в запросе NetrServerAuthenticate3 и в случае успешного выполнения создает соединение по протоколу Netlogon с контроллером домена.
Функция try_zerologon(dc_handle, rpc_con, target_computer) пытается установить пустой пароль учетной записи, отправляя запрос NetrServerPasswordSet2 на контроллер домена.
Внутри функции perform_attack(dc_handle, dc_ip, target_computer) описывается очередность работы функций try_zerologon_authenticate и try_zerologon. Если try_zerologon_authenticate выполняется успешно, то вызывается try_zerologon.
Есть несколько отличий исполнения данного эксплойта от функции в Mimikatz:
Эксплойт использует более новый метод NetrServerAuthenticate3 и отличие NetrServerAuthenticate2 от него заключается лишь в отсутствии параметра AccountRid;
Эксплойт каждый раз при запросах NetrServerReqChallenge и NetrServerAuthenticate3 заново вызывает EPM. В Mimikatz EPM вызывается единожды, а затем уже идут вызовы NetrServerReqChallenge и NetrServerAuthenticate2.
На этом этапе разбор инструментов завершается, так как все остальные существующие эксплойты действуют по такому же алгоритму и используют стандартные методы MS-NRPC.
Дальше я предлагаю посмотреть, как выглядит трафик при попытке воспользоваться уязвимостью Zerologon, в случае когда у нас обновлен контроллер домена, то есть уязвимость уже пропатчена.
Попытки эксплуатации Zerologon на пропатченном контроллере домена
При попытке провести атаку на пропатченном контроллере домена в сетевом трафике видны только повторяющиеся методы NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate2 (Opnum 15) или (NetrServerAuthenticate3 (Opnum 26) с ответом ошибки от сервера (рисунок 16 и рисунок 17):
Естественно, метода NetrServerPasswordSet2 (Opnum 30) здесь быть не может.
Давайте воспользуемся еще одним источником информации и способом мониторинга вызовов RPC функций - ETW (Event Tracing for Windows).
Анализ событий RPC
Как уже говорилось ранее в статьях RPC и способы его мониторинга и Возможные варианты детектирования DCSync, в случае с RPC - ETW дает возможность логировать вызовы функций через него, позволяя управлять этими логами, как и любыми другими из EventLog.
Для этого используется RPC провайдер Microsoft-Windows-RPC с GUID: {6AD52B32-D609-4BE9-AE07-CE8DAE937E39}. RPC функции идентифицируются по номеру интерфейса UUID и номеру операции opnum (procmon). При этом номер интерфейса распознает группу связанных удаленных функций. Функциям MS-NETLOGON соответствует идентификатор UUID 12345678-1234-abcd-ef00-01234567cffb.
На первом этапе происходит подключение клиента по порту 135 к протоколу удаленного вызова процедур (RPC) Microsoft Endpoint Mapper (EPM), которому соответствует UUID e1af8308-5d1f-11c9-91a4-08002b14a0fa (рисунок 18). EPM- служба, выделяющая приложению динамический порт RPC.
Служба EPM возвращает клиенту номер динамического RPC порта, в данном случае 49675, после чего происходит подключение к нему и затем идет вызов RPC функций Netlogon.
Следующий этап - это повторяющиеся вызовы методов NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate2 (Opnum 15) за короткий промежуток времени (рисунок 19 и 20).
Напомню, что в случае эксплойта, основанного на библиотеках Impacket, эксплоит ведет себя по другому. Он каждый раз вызывает EPM, а затем пары методов: NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate3 (Opnum 26), и так каждую итерацию перед изменением пароля.
На заключительном этапе методом NetrServerPasswordSet2 (Opnum 30) для учетной записи компьютера контроллера домена устанавливается пароль (рисунок 22).
В качестве детекта при эксплуатации Zerologon можно использовать многократно повторяющиеся вызовы методов NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate2 (Opnum 15) или NetrServerAuthenticate3 (Opnum 26), однако есть несколько НО, о которых мы упоминали ранее в статье про DCSync:
лог RPC относится к логам отладки;
на выходе мы имеем большой поток сложно обрабатываемых событий;
по логам RPC нельзя определить источник вызовов.
Предлагаю посмотреть еще один альтернативный и скорее дополнительный способ анализа событий MS-NRPC - журнал отладки Netlogon.
Журнал отладки службы Netlogon
Для того чтобы включить журнал отладки службы Netlogon, необходимо выполнить следующие команды:
nltest /dbflag:0x2080ffff
net stop netlogon
net start netlogon
Сам журнал пишется в файл Netlogon.txt в директории C:\Windows\debug.
Давайте проанализируем, что конкретно записывается в этот журнал во время атаки Zerologon.
Анализ журнала отладки Netlogon
На рисунке 23 показан вывод журнала Netlogon:
В нем мы увидим попытки аутентификации и сброс пароля. Также здесь можно найти MD5 хэш пароля, который был установлен для учетной записи контроллера домена.
Этот способ обнаружения атаки скорее дополнительный и не совсем уместный с точки зрения отображения в SIEM-системах. Возможно, более точно обнаружить эксплуатацию уязвимости у нас получится с помощью событий из журнала Windows, поэтому предлагаю перейти к их анализу.
Анализ Windows EventViewer
Нас будут интересовать события из 2-х журналов: Security и System.
Журнал Security:
EventID 4742 - A computer account was changed;
Настройка политики
Для точного присутствия события с EventID 4742 необходимо включить политику Audit Computer Account Management (путь: Computer Configuration\Policies\Windows Settings\Security Settings\Advanced Audit Policy Configuration\Audit Policies\Account Management\Audit Computer Account Management).
Журнал System, это события непосредственно службы Netlogon:
EventID 5805 - The session setup from the computer failed to authenticate. The following error occurred: Access is denied
EventID 5823 - The system successfully changed its password on the domain controller. This event is logged when the password for the computer account is changed by the system. It is logged on the computer that changed the password.
EventID 5723 - The session setup from computer failed because the security database does not contain a trust account referenced by the specified computer.
Пример обнаружения атаки в логах
При легитимной смене пароля параллельно с событием журнала Security с EventID 4742 генерируется событие с EventID 5823 журнала System (оно означает, что учетная запись компьютера была легитимно изменена системой). Поэтому, если есть событие с EventID 4742 с отметкой о смене пароля (важно смотреть на дату), но отсутствует событие с EventID 5823 - это прямое свидетельство эксплуатации уязвимости Zerologon.
Пример легитимного поведения показан на рисунках 24 и 25 ниже:
Если в журнале одновременно появляются события с EventID 5805, возникающее вследствие неуспешных попыток аутентификации Netlogon на контроллере домена, и EventID 4742, то это говорит нам об успешной эксплуатации уязвимости Zerologon.
Стоит отметить,что в случае эксплуатации уязвимости на пропатченном контроллере домена, событие с EventID 5805 все равно будет присутствовать в журнале.
Также может появляться событие с EventID 5723, оно возникает если атакующий введет компьютерную учетную запись с ошибкой или же несуществующую компьютерную учетную запись.
Теперь, когда мы посмотрели различные источники, которые могут помочь нам при обнаружении эксплуатации Zerologon, попробуем составить возможные варианты псевдо-правил детектирования.
Возможные варианты детектирования на основе журнала Windows
Предлагаем построить 2 варианта детекта: первый будет основываться на событиях из журналов Security и System (EventID 4742 и EventID 5805), а второй только на журнале System (EventID 5723 и EventID 5805).
Первый вариант
SELECT *
FROM EventCode=5805
WHERE (Computer) IN
(
SELECT (Computer)
FROM EventCode=4742
WHERE
src_user= "ANONYMOUS LOGON" AND
PasswordLastSet!= "-" AND
Target_User_Name= "DC*$"
)
Логика детектирования здесь следующая: если на одном и том же контроллере домена в течение нескольких минут появляются события об изменении машинной учетной записи контроллера домена (именно изменение пароля) и событие о том, что сессия не прошла проверку подлинности, то мы имеем дело с эксплуатацией уязвимости Zerologon.
Второй вариант детекта
В событии EventID 5805 в поле EventData может быть какое угодно имя компьютера (рисунок 29), по умолчанию для Mimikatz это mimikatz, но поскольку оно может быть любым, поэтому основывать детект именно на имени компьютера не стоит.
SELECT *
FROM EventCode=5805
WHERE (AttackerHost, Computer) IN
(
SELECT (AttackerHost, Computer)
FROM EventCode=5723
WHERE
Computer= "DC*$"
)
Второе правило детектирования говорит о следующем: если на одном и том же контроллере домена в течение нескольких минут появляются события об установлении сессии от имени несуществующей учетной записи и о том, что сессия не прошла проверку подлинности, то мы имеем дело с попыткой эксплуатации уязвимости Zerologon.
Выводы
Стоит отметить, что детект на основе логов возможен, но это скорее будет только индикатором возможной атаки, критически важной информации (например, источник атаки) из них мы не сможем извлечь.
Не исключены и ложные сработки, например, по событию 5805, так как оно может возникнуть не только вследствие попыток эксплуатации уязвимости, но и когда на конкретной машине в домене что-то поломалось, и она "выпала" из него. То же самое можно сказать и про событие 5723, например, оно возникает в результате конфликта репликаций. Смотреть на имя компьютера в этих событиях, конечно, можно. Но его запросто можно изменить, отредактировав код эксплойта.
В дополнение к этим событиям существует еще возможность смотреть и события ETW, но лог RPC относится к логам отладки. Событий слишком много, и определить источник вызовов мы не можем. Поэтому детект только на журналах Windows имеет место быть, но не особо информативен, и это не панацея.
Для полноценного детектирования рекомендуется использовать мониторинг трафика, где однозначно видны ip-адреса участников взаимодействия, а распознать попытку эксплуатации можно по многократно повторяющимся методам NetrServerReqChallenge (Opnum 4) и NetrServerAuthenticate2/3 (Opnum 15) в трафике от единственного источника за промежуток времени в несколько секунд. а в случае успешной эксплуатации вслед за этими методами можно увидеть метод NetrServerPasswordSet (или NetrServerPasswordSet2) от этого же источника. Также при построении детекта важно помнить, что однозначно основываться на NegotiateFlag, равном 0*212fffff,
нельзя, набор битов может быть любой, за исключением наличия бита, отвечающего за шифрование AES-CFB8.
Желательно, чтобы на контроллерах домена был включен журнал отладки Netlogon, так как в нем тоже можно отследить попытки эксплуатации Zerologon и установку пустого пароля. Однако отслеживать изменения в этом журнале будет достаточно проблематично.
Заключение
В этой статье мною были рассмотрены два инструмента для проведения атаки Zerologon: модуль Mimikatz и эксплойт CVE-2020-1472, у которых есть свои отличительные особенности, если говорить про их кодовую реализацию, но они имеют одинаковую логику эксплуатации уязвимости и используют известные MS-NRPC методы для реализации атаки.
Также я разобрала возможные способы детектирования Zerologon и пришли к выводу, что одними логами из журнала Windows обойтись нельзя. Параллельно необходимо мониторить сетевой трафик, он и будет являться более информативным в этом случае.
Помните про важность своевременных обновлений! Надеюсь, статья оказалась вам полезной.
Благодарю за внимание!
Автор: Мавлютова Валерия (@iceflipper), младший аналитик-исследователь киберугроз в компании R-Vision