Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
375 views
in Technique[技术] by (71.8m points)

windows - Do high-integrity tokens *have* to have the Administrators group enabled?

When UAC is enabled, and you log in with an administrative account, you get two tokens:

  • the elevated token; this has the Administrators group enabled, is high integrity (i.e., the mandatory integrity label SID is S-1-16-12288) and has elevation type TokenElevationTypeFull.

  • the limited token; this has the Administrators group disabled, is medium integrity (S-1-16-8192) and has elevation type TokenElevationTypeLimited.

Do these three factors always match up in this way? That is, does the kernel require that only tokens with the Administrators group enabled can have high integrity and/or TokenElevationTypeFull?

Are there any circumstances under which a process will not have Administrators privilege but will be running with high integrity and/or TokenElevationTypeFull?

(Rationale for the question: the answer affects the ways in which a programmer can safely test for elevated privileges. For example, it came up here.)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, the kernel does not require that the integrity level and elevation type of a token match up with the status of the Administrators group. This means that a process having a high integrity level, or TokenElevationTypeFull, does not necessarily have administrator access.

In particular, note that using runas /trustlevel:0x20000 from an administrative command prompt will result in a process that does not have administrator privilege but nonetheless runs with high integrity and (if UAC is enabled) will have TokenElevationTypeFull. (As discovered here.) I believe this represents a bug in runas.

This sample code demonstrates the behaviour; if run with admin privilege, it launches a subprocess with the administrators group (and all privileges except SeChangeNotifyPrivilege) disabled but which is still running with high integrity and 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
", GetLastError());
        return;
    }

    if (!CheckTokenMembership(itoken, admins_sid, &is_enabled))
    {
        printf("CheckTokenMembership: %u
", GetLastError());
        CloseHandle(itoken);
        return;
    }

    CloseHandle(itoken);

    printf("Administrators group enabled: %u
", 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
", GetLastError());
        return;
    }

    if (!ConvertSidToStringSidA(token_mandatory_label->Label.Sid, &stringsid))
    {
        printf("ConvertSidToStringSid: %u
", GetLastError());
        return;
    }

    printf("SID: %s
", stringsid);
}

void get_elevation(HANDLE token)
{
    TOKEN_ELEVATION_TYPE elevation;
    DWORD dw;

    if (!GetTokenInformation(token, 
        TokenElevationType, &elevation, sizeof(elevation), &dw))
    {
        printf("GetTokenInformation: %u
", GetLastError());
        return;
    }

    printf("Elevation type : %u
", (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
", GetLastError());
        return;
    }

    printf("token1:
");
    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
", GetLastError());
        return;
    }

    printf("token2:
");
    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
", 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
", GetLastError());
            return 1;
        }
    }

    test();
    return 0;
}

Output when run from an elevated command prompt:

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

If you run the sample code again from the child process, you can confirm that the child process did retain these properties:

token1:
Administrators group enabled: 0
SID: S-1-16-12288
Elevation type : 2

If UAC is disabled, the elevation type is TokenElevationTypeDefault but otherwise the outcome is the same:

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

As expected, the limited token looks like this:

token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 3

Or if you're logged in as a non-admin user, whether UAC is enabled or not:

token1:
Administrators group enabled: 0
SID: S-1-16-8192
Elevation type : 1

(All tests run on Windows 7 SP1 x64.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...