高完整性令牌*是否具有启用pipe理员组?

当启用UAC并且使用pipe理帐户login时,您会得到两个令牌:

这三个因素总是以这种方式匹配吗? 也就是说,内核是否要求只有启用pipe理员组的令牌可以具有较高的完整性和/或TokenElevationTypeFull?

有什么情况下进程不具有pipe理员权限,但将以高完整性和/或TokenElevationTypeFull运行?

(这个问题的理由:答案会影响到程序员可以安全地testing升级权限的方式,例如, 这里提到了 )

Solutions Collecting From Web of "高完整性令牌*是否具有启用pipe理员组?"

不,内核不要求令牌的完整性级别和高程类型与管理员组的状态相匹配。 这意味着具有高完整性级别或TokenElevationTypeFull的进程不一定具有管理员访问权限。

尤其要注意的是,从管理命令提示符使用runas /trustlevel:0x20000将导致进程没有管理员权限,但仍然以高完整性运行(如果启用UAC)将具有TokenElevationTypeFull。 ( 正如我们在这里所发现的 )我相信这代表了runas一个bug。

这个示例代码演示了这个行为。 如果以管理员权限运行,它将启动管理员组(除了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上运行。)