Абьюз сессий Windows по-новому. Получаем билеты TGT методом GIUDA

Содержание статьи

  • Logon Session
  • Как LSA запрашивает билеты Kerberos
  • Крадем билет
  • TGT — это TGS
  • Выводы

Есть раз­ные спо­собы зло­упот­реблять сес­сией поль­зовате­ля на устрой­стве: кра­жа учет­ных дан­ных, манипу­ляции с токена­ми и дру­гие. Но зна­ешь ли ты, что мож­но сымити­ровать получе­ние TGT-билета поль­зовате­лем через совер­шенно легитим­ные фун­кции Windows? warning

Статья име­ет озна­коми­тель­ный харак­тер и пред­назна­чена для спе­циалис­тов по безопас­ности, про­водя­щих тес­тирова­ние в рам­ках кон­трак­та. Автор и редак­ция не несут ответс­твен­ности за любой вред, при­чинен­ный с при­мене­нием изло­жен­ной информа­ции. Рас­простра­нение вре­донос­ных прог­рамм, наруше­ние работы сис­тем и наруше­ние тай­ны перепис­ки прес­леду­ются по закону.

В этом году появи­лось нес­коль­ко новых спо­собов из такого раз­ряда. Наибо­лее инте­рес­ные — WTSImpersonator и GIUDA. Пос­ледний поз­воля­ет получать тикеты залоги­нен­ного поль­зовате­ля, даже не зная его пароля! Давай раз­берем­ся, как это работа­ет, а парал­лель­но напишем реали­зацию на C++, которую я наз­вал TGSThief.

 

Logon Session

При вхо­де поль­зовате­ля в Windows появ­ляет­ся сес­сия поль­зовате­ля, которая хра­нит все дан­ные о нем. Для каж­дого нового поль­зовате­ля соз­дает­ся новая сес­сия. Нап­ример, если на компь­юте­ре одновре­мен­но работа­ют два поль­зовате­ля, то будет две сес­сии.

Как выг­лядят Logon Sessions

Каж­дая сес­сия опре­деля­ется с помощью LUID (locally unique identifier). Из наз­вания понят­но, что LUID уни­кален для каж­дой сес­сии. Информа­ция хра­нит­ся в виде одно­имен­ной струк­туры.

typedef struct _LUID { ULONG LowPart; LONG HighPart;} LUID, *PLUID;

Сам LUID пред­став­лен в виде двух зна­чений: ULONG и LONG. При­чем обыч­но запол­няет­ся лишь поле LowPart, а HighPart име­ет зна­чение 0.

Эта струк­тура исполь­зует­ся во всех фун­кци­ях WinAPI, которые так или ина­че свя­заны с сес­сиями поль­зовате­ля.

С помощью GetTokenInformation() мож­но получить LUID поль­зовате­ля. Для это­го фун­кции сле­дует передать токен про­цес­са, запущен­ного от име­ни текуще­го поль­зовате­ля.

#include <windows.h>#include <iostream>#include <sddl.h>int main() { HANDLE tokenHandle; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tokenHandle)) { std::cerr << "Ошибка OpenProcessToken: " << GetLastError() << std::endl; return 1; } DWORD tokenInformationLength = 0; GetTokenInformation(tokenHandle, TokenStatistics, nullptr, 0, &tokenInformationLength); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { std::cerr << "GetTokenInformation неудачный первый вызов: " << GetLastError() << std::endl; CloseHandle(tokenHandle); return 1; } TOKEN_STATISTICS* tokenStats = reinterpret_cast<TOKEN_STATISTICS*>(new BYTE[tokenInformationLength]); if (tokenStats == nullptr) { std::cerr << "Ошибка выделения памяти для TOKEN_STATISTICS" << std::endl; CloseHandle(tokenHandle); return 1; } if (!GetTokenInformation(tokenHandle, TokenStatistics, tokenStats, tokenInformationLength, &tokenInformationLength)) { std::cerr << "Ошибка GetTokenInformation: " << GetLastError() << std::endl; delete[] tokenStats; CloseHandle(tokenHandle); return 1; } std::cout << "LUID: " << std::hex << "0x" << std::uppercase << tokenStats->AuthenticationId.LowPart << tokenStats->AuthenticationId.HighPart << std::endl; delete[] tokenStats; CloseHandle(tokenHandle); return 0;}

Ин­форма­ция о LUID поль­зовате­ля упа­дет в поле AuthenticationId струк­туры TOKEN_STATISTICS.

typedef struct _TOKEN_STATISTICS { LUID TokenId; LUID AuthenticationId; LARGE_INTEGER ExpirationTime; TOKEN_TYPE TokenType; SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; DWORD DynamicCharged; DWORD DynamicAvailable; DWORD GroupCount; DWORD PrivilegeCount; LUID ModifiedId;} TOKEN_STATISTICS, *PTOKEN_STATISTICS;

Имен­но на манипу­ляци­ях с LUID осно­вана логика инс­тру­мен­та GIUDA. Фак­тичес­ки идет под­мена LUID, что откры­вает воз­можность зап­росить билет от лица поль­зовате­ля, чья сес­сия прос­то при­сутс­тву­ет на устрой­стве. Свой LUID мы получать научи­лись, а как получать LUID дру­гих поль­зовате­лей?

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *