stihl не предоставил(а) никакой дополнительной информации.
Механизм RecoveryMode в Windows LAPS позволяет расшифровывать пароли локальных администраторов даже при удаленных «дешифраторах». В статье ты узнаешь, как это сделать, а вишенка на торте — proof-of-concept RPC-интерфейса, который умеет безопасно и скрытно запрашивать LAPS-пароли прямо из SYSTEM-контекста на контроллере домена.
Это исследование получило первое место на Для просмотра ссылки Войдиили Зарегистрируйся в категории «Раз bypass, два bypass». Соревнование ежегодно проводится компанией Awillix.
Однажды в небезызвестном чатике RedTeam Brazzers Для просмотра ссылки Войдиили Зарегистрируйся о том, как сейчас работает обновленный механизм смены паролей локальных администраторов в AD — Windows LAPS (ранее Microsoft LAPS, теперь называемый Legacy LAPS). Там же обсудили и другой момент: можно ли при атаке DCSync за один раз получить пароли всех локальных админов. Оказалось, что да — в Legacy LAPS эти пароли хранятся в LDAP как защищенные свойства, но без шифрования.
Для просмотра ссылки Войдиили Зарегистрируйся
Однако такой же трюк не пройдет, если в инфраструктуре заказчика используется актуальный Windows LAPS, расшифрование паролей в котором проходит по протоколу MS-GKDI. Кроме того, в этом случае в домене AD можно задать только одного конкретного «дешифратора паролей» — учетную запись или группу пользователей, которым разрешено читать пароли локальных админов.
Для просмотра ссылки Войдиили Зарегистрируйся
Мы задумались: как пентестеру закрепиться в Windows LAPS так, чтобы после получения максимальных прав в AD можно было в любой момент запросить пароль любого локального администратора, управляемого LAPS, даже если сменятся пароли у «расшифровщиков», имеющих доступ к этим данным?
В этом помогла одна особенность устройства Windows LAPS на контроллерах домена.
или Зарегистрируйся, можно увидеть одну странную опцию -RecoveryMode у командлета Get-LapsADPassword.
Для просмотра ссылки Войдиили ЗарегистрируйсяДля просмотра ссылки Войди или Зарегистрируйся
Внимательный читатель уже мог ее заметить Для просмотра ссылки Войдиили Зарегистрируйся ресерчера XPN, когда тот исследовал сборку lapspsh.dll.
Для просмотра ссылки Войдиили Зарегистрируйся
Поскольку модуль lapspsh.dll — это всего лишь Managed-обертка над нативной DLL lapsutil.dll, можно пойти дальше: открыть ее в дизассемблере и найти экспортируемую функцию DecryptRecoveryMode.
Для просмотра ссылки Войдиили Зарегистрируйся
Далее, следуя по пути из хлебных крошек, можно сделать то же самое для серверной части LAPS — библиотеки C:\Windows\System32\laps.dll.
Для просмотра ссылки Войдиили Зарегистрируйся
Здесь почти черным по белому (синим по черному) написано, что, если LapsCore:
arseSidProtectionString завершается ошибкой (возвращает значение, отличное от нуля), логика передается функции GetTokenForRecoveryModeDecryption, которая, в свою очередь, проверяет вызывающую УЗ на соответствие NT AUTHORITY\SYSTEM и в случае успеха отдает токен для резервного восстановления пароля LAPS.
Для просмотра ссылки Войдиили Зарегистрируйся
Таким образом, мы как атакующие можем злоупотребить этой особенностью Windows LAPS для сохранения постоянного доступа к расшифровывающему API без привязки к конкретному субъекту «дешифратора».
Для просмотра ссылки Войдиили Зарегистрируйся
Остается один незначительный аспект — обеспечить для себя постоянный контекст исполнения LocalSystem на контроллере домена. Как мы подумали, это отличный кейс для практики написания наступательного RPC-интерфейса!
или Зарегистрируйся коллег из Orange Cyberdefense.
Мы спроектировали RPC-эндпоинт следующим образом: на вход — DN компьютера, пароль локального администратора на котором мы хотим получить, и 8-байтовый ключ аутентификации, а на выходе — расшифрованное значение запрошенного пароля.
Порядок использования функциональности режима восстановления LAPS можно зареверсить из декомпилированного кода соответствующих процедур библиотеки lapsutil.dll либо подсмотреть, как это делается в lapspsh.dll.
И в итоге прийти к такому определению интерфейса.
Чтобы сгенерировать сигнатуры lapsutil.dll для ее статической линковки в сервер, мы воспользовались стандартной SDK Visual Studio:
Для тестирования серверную часть написали дебажным выводом в консоль, а клиентскую реализовали на C++.
Для просмотра ссылки Войдиили Зарегистрируйся
В продовом варианте сервер можно установить как службу, а клиент портировали на Python с использованием Impacket.
Для просмотра ссылки Войдиили ЗарегистрируйсяДля просмотра ссылки Войди или Зарегистрируйся
Разумеется, для повышения операционной безопасности сервисный бинарь можно также при помощи Impacket устанавливать удаленно или же полностью отказаться от использования службы и запускать сервер из памяти посредством бесфайловых техник исполнения — что оставим на усмотрение читателя.
Для просмотра ссылки Войдиили Зарегистрируйся
full source: Для просмотра ссылки Войдиили Зарегистрируйся
Это исследование получило первое место на Для просмотра ссылки Войди
Однажды в небезызвестном чатике RedTeam Brazzers Для просмотра ссылки Войди
Для просмотра ссылки Войди
Однако такой же трюк не пройдет, если в инфраструктуре заказчика используется актуальный Windows LAPS, расшифрование паролей в котором проходит по протоколу MS-GKDI. Кроме того, в этом случае в домене AD можно задать только одного конкретного «дешифратора паролей» — учетную запись или группу пользователей, которым разрешено читать пароли локальных админов.
Для просмотра ссылки Войди
Мы задумались: как пентестеру закрепиться в Windows LAPS так, чтобы после получения максимальных прав в AD можно было в любой момент запросить пароль любого локального администратора, управляемого LAPS, даже если сменятся пароли у «расшифровщиков», имеющих доступ к этим данным?
В этом помогла одна особенность устройства Windows LAPS на контроллерах домена.
Да кто такой этот ваш RecoveryMode?!
Если обратиться к (очень скудной) Для просмотра ссылки ВойдиДля просмотра ссылки Войди
Внимательный читатель уже мог ее заметить Для просмотра ссылки Войди
Для просмотра ссылки Войди
Поскольку модуль lapspsh.dll — это всего лишь Managed-обертка над нативной DLL lapsutil.dll, можно пойти дальше: открыть ее в дизассемблере и найти экспортируемую функцию DecryptRecoveryMode.
Для просмотра ссылки Войди
Далее, следуя по пути из хлебных крошек, можно сделать то же самое для серверной части LAPS — библиотеки C:\Windows\System32\laps.dll.
Для просмотра ссылки Войди
Здесь почти черным по белому (синим по черному) написано, что, если LapsCore:
Для просмотра ссылки Войди
Таким образом, мы как атакующие можем злоупотребить этой особенностью Windows LAPS для сохранения постоянного доступа к расшифровывающему API без привязки к конкретному субъекту «дешифратора».
Для просмотра ссылки Войди
Остается один незначительный аспект — обеспечить для себя постоянный контекст исполнения LocalSystem на контроллере домена. Как мы подумали, это отличный кейс для практики написания наступательного RPC-интерфейса!
Offensive LAPS RPC
Хорошее начало для разработки такого интерфейса — статья Для просмотра ссылки ВойдиМы спроектировали RPC-эндпоинт следующим образом: на вход — DN компьютера, пароль локального администратора на котором мы хотим получить, и 8-байтовый ключ аутентификации, а на выходе — расшифрованное значение запрошенного пароля.
Код:
[
uuid(12345678-1234-1234-1234-1234567890ab),
version(1.0),
implicit_handle(handle_t ImplicitHandle)
]
interface DecryptRecoveryLAPS
{
error_status_t DecryptPassword(
[in, string] const wchar_t* dn,
[in, size_is(authKeyLen)] const unsigned char* authKey,
[in] unsigned int authKeyLen,
[out, string] wchar_t** result
);
}
Порядок использования функциональности режима восстановления LAPS можно зареверсить из декомпилированного кода соответствующих процедур библиотеки lapsutil.dll либо подсмотреть, как это делается в lapspsh.dll.
[DllImport("lapsutil.dll", CharSet = CharSet.Unicode)]
public static extern uint DecryptRecoveryMode(IntPtr pbData, uint cbData, out IntPtr pbDecryptedData, out uint cbDecryptedData);
И в итоге прийти к такому определению интерфейса.
Код:
#pragma comment(lib, "lapsutil.lib")
extern "C" __declspec(dllimport) unsigned int __cdecl DecryptRecoveryMode(
unsigned char* __ptr64,
unsigned int,
unsigned char* __ptr64* __ptr64,
unsigned int* __ptr64
);
UINT DecryptBytesHelper(BYTE* encryptedData, UINT encryptedSize, BYTE** decryptedBytes, UINT* decryptedSize)
{
UINT ret = DecryptRecoveryMode(encryptedData, encryptedSize, decryptedBytes, decryptedSize);
if (ret != 0)
debug_print(L"[-] DecryptRecoveryMode failed with error code: %u\n", ret);
return ret;
}
Чтобы сгенерировать сигнатуры lapsutil.dll для ее статической линковки в сервер, мы воспользовались стандартной SDK Visual Studio:
dumpbin /exports lapsutil.dll > lapsutil.def\
lib /def:lapsutil.def /out:lapsutil.lib /machine:x64
Для тестирования серверную часть написали дебажным выводом в консоль, а клиентскую реализовали на C++.
Для просмотра ссылки Войди
В продовом варианте сервер можно установить как службу, а клиент портировали на Python с использованием Impacket.
Для просмотра ссылки Войди
Разумеется, для повышения операционной безопасности сервисный бинарь можно также при помощи Impacket устанавливать удаленно или же полностью отказаться от использования службы и запускать сервер из памяти посредством бесфайловых техник исполнения — что оставим на усмотрение читателя.
Для просмотра ссылки Войди
full source: Для просмотра ссылки Войди