Нет, ядро не требует, чтобы уровень целостности и тип высоты из токена совпадают со статусом группы «Администраторы». Это означает, что процесс с высоким уровнем целостности или TokenElevationTypeFull не обязательно имеет доступ администратора.
В частности, отметить, что с помощью runas /trustlevel:0x20000
от административно-командной строки приведет к процессу, который не имеет права администратора, но тем не менее, работает с высокой целостностью и (если UAC включен) будет иметь TokenElevationTypeFull. (As discovered here.) Я считаю, что это ошибка в runas
.
Этот образец кода демонстрирует поведение; если он запускается с правами администратора, он запускает подпроцесс с группой администраторов (и все привилегии, за исключением SeChangeNotifyPrivilege) отключены, но которые все еще работают с высокой степенью целостности и TokenElevationTypeFull.
#include <Windows.h>
#include <Sddl.h>
#include <stdio.h>
PSID admins_sid;
void get_membership(HANDLE token)
{
BOOL is_enabled;
HANDLE itoken;
if (!DuplicateToken(token, SecurityIdentification, &itoken))
{
printf("DuplicateToken: %u\n", GetLastError());
return;
}
if (!CheckTokenMembership(itoken, admins_sid, &is_enabled))
{
printf("CheckTokenMembership: %u\n", GetLastError());
CloseHandle(itoken);
return;
}
CloseHandle(itoken);
printf("Administrators group enabled: %u\n", is_enabled);
return;
}
void get_integrity(HANDLE token)
{
char buffer[4096];
char * stringsid;
TOKEN_MANDATORY_LABEL *token_mandatory_label = (TOKEN_MANDATORY_LABEL *)buffer;
DWORD dw;
if (!GetTokenInformation(token, TokenIntegrityLevel, buffer, sizeof(buffer), &dw))
{
printf("GetTokenInformation: %u\n", GetLastError());
return;
}
if (!ConvertSidToStringSidA(token_mandatory_label->Label.Sid, &stringsid))
{
printf("ConvertSidToStringSid: %u\n", GetLastError());
return;
}
printf("SID: %s\n", stringsid);
}
void get_elevation(HANDLE token)
{
TOKEN_ELEVATION_TYPE elevation;
DWORD dw;
if (!GetTokenInformation(token,
TokenElevationType, &elevation, sizeof(elevation), &dw))
{
printf("GetTokenInformation: %u\n", GetLastError());
return;
}
printf("Elevation type : %u\n", (DWORD)elevation);
}
void test(void)
{
HANDLE token1, token2;
SID_AND_ATTRIBUTES sids_to_disable;
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
PROCESS_INFORMATION pi;
if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token1))
{
printf("OpenProcessToken: %u\n", GetLastError());
return;
}
printf("token1:\n");
get_membership(token1);
get_integrity(token1);
get_elevation(token1);
sids_to_disable.Attributes = 0;
sids_to_disable.Sid = admins_sid;
if (!CreateRestrictedToken(token1,
DISABLE_MAX_PRIVILEGE, 1, &sids_to_disable, 0, NULL, 0, NULL, &token2))
{
printf("CreateRestrictedToken: %u\n", GetLastError());
return;
}
printf("token2:\n");
get_membership(token2);
get_integrity(token2);
get_elevation(token2);
if (!CreateProcessAsUserA(token2,
NULL, "cmd", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
printf("CreateProcessAsUser: %u\n", GetLastError());
return;
}
}
int main(int argc, char ** argv)
{
{
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
if(! AllocateAndInitializeSid(&SIDAuth, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&admins_sid))
{
printf("AllocateAndInitializeSid: %u\n", GetLastError());
return 1;
}
}
test();
return 0;
}
Выход при запуске из командной строки с повышенными:
token1:
Administrators group enabled: 1
SID: S-1-16-12288
Elevation type : 2
token2:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 2
Если запустить пример кода снова дочернего процесса, вы можете подтвердить, что дочерний процесс сделал сохранить эти свойства:
token1:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 2
Если UAC отключен, тип отметки - TokenElevationTypeDefault, но в остальном результат тот же:
token1:
Administrators group enabled: 1
SID: S-1-16-12288
Elevation type : 1
token2:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 1
Как и ожидалось, ограниченный маркер выглядит следующим образом:
token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 3
Или, если вы вошли в систему как пользователь без прав администратора, включен ли UAC или нет:
token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 1
(Все тесты выполняются на Windows 7 SP1 x64.)
Это сбой для меня в Windows 10 x64. Код ошибки: «STATUS_DLL_INIT_FAILED'. Это происходит так же, как conhost.exe выполняется, но до того, как он создаст новое окно. Я проверил, что как дочерние процессы cmd.exe, так и conhost.exe имеют группу «Администраторы», установленные только для отказа и высокой целостности. Это может быть ошибка в Windows 10 или указание на предположение о том, что процесс высокой целостности имеет права администратора. Моя версия Windows 10 устарела (10.0.10074); он может работать в новой версии. – eryksun
@eryksun: вы имеете в виду дочерний экземпляр cmd.exe сбой? Похоже, что это связано с разрешениями на рабочем столе/оконной станции. (Неужели он все еще падает, если вы не используете CREATE_NEW_CONSOLE, позволяя ему наследовать существующую консоль?) У меня есть современная установка Windows 10 дома, если у меня есть время, я попробую это сегодня вечером. –
Наверняка это связано с созданием новой консоли. Как я уже сказал, дочерний cmd.exe терпит неудачу (возможно, инициализация kernelbase, но я не проверял), когда запускается новый экземпляр conhost.exe. Если я удалю 'CREATE_NEW_CONSOLE' и дождитесь обработки дескриптора, это нормально. – eryksun