2015-06-21 7 views
3

Когда UAC включен, и вы войдите в систему с учетной записью администратора, вы получите два маркера:Знаки с высокой степенью целостности * имеют *, чтобы включить группу «Администраторы»?

  • поднятый маркер; это имеет включенную группу «Администраторы», имеет высокую целостность (т. е. обязательный идентификатор целостности SID - S-1-16-12288) и имеет тип отметки TokenElevationTypeFull.

  • ограниченный токен; это отключает группу «Администраторы», является целостностью среды (S-1-16-8192) и имеет тип отметки TokenElevationTypeLimited.

Связаны ли эти три фактора таким образом? То есть в ядре требуется, что только токены с включенной группой «Администраторы» могут иметь высокую целостность и/или TokenElevationTypeFull?

Существуют ли какие-либо обстоятельства, при которых процесс не будет иметь права администратора, но будет работать с высокой степенью целостности и/или TokenElevationTypeFull?

(Обоснование для вопроса:. Ответ влияет на способы, в которых программист может безопасно испытать для повышенных привилегий, например, it came up here.)

ответ

2

Нет, ядро ​​не требует, чтобы уровень целостности и тип высоты из токена совпадают со статусом группы «Администраторы». Это означает, что процесс с высоким уровнем целостности или 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.)

+0

Это сбой для меня в Windows 10 x64. Код ошибки: «STATUS_DLL_INIT_FAILED'. Это происходит так же, как conhost.exe выполняется, но до того, как он создаст новое окно. Я проверил, что как дочерние процессы cmd.exe, так и conhost.exe имеют группу «Администраторы», установленные только для отказа и высокой целостности. Это может быть ошибка в Windows 10 или указание на предположение о том, что процесс высокой целостности имеет права администратора. Моя версия Windows 10 устарела (10.0.10074); он может работать в новой версии. – eryksun

+0

@eryksun: вы имеете в виду дочерний экземпляр cmd.exe сбой? Похоже, что это связано с разрешениями на рабочем столе/оконной станции. (Неужели он все еще падает, если вы не используете CREATE_NEW_CONSOLE, позволяя ему наследовать существующую консоль?) У меня есть современная установка Windows 10 дома, если у меня есть время, я попробую это сегодня вечером. –

+0

Наверняка это связано с созданием новой консоли. Как я уже сказал, дочерний cmd.exe терпит неудачу (возможно, инициализация kernelbase, но я не проверял), когда запускается новый экземпляр conhost.exe. Если я удалю 'CREATE_NEW_CONSOLE' и дождитесь обработки дескриптора, это нормально. – eryksun