2015-06-21 48 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一個過程。 (​​)我認爲這代表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進程都將Administrators組設置爲只拒絕和高完整性。這可能是Windows 10中的一個錯誤,或者表明一個假設某個高完整性進程具有管理員權限。我的Windows 10版本過時(10.0.10074);它可能在更新的版本中工作。 – eryksun

+0

@eryksun:你的意思是cmd.exe的子實例崩潰?聽起來像是與桌面/窗口站的權限有關。 (如果您不使用CREATE_NEW_CONSOLE,是否仍然會崩潰,讓它繼承現有的控制檯?)我已經在家裏安裝了最新的Windows 10安裝程序,如果我有時間我會在今晚嘗試它。 –

+0

肯定是由於創建了一個新的控制檯。就像我說的,當新的conhost.exe實例啓動時,子cmd.exe失敗(可能是kernelbase的初始化,但我沒有檢查)。如果我刪除了'CREATE_NEW_CONSOLE'並等待進程句柄,那就好了。 – eryksun

相關問題