can't get sacl of a file

792 Views Asked by At

I want to know the the integrity levef of a file, but can't get sacl. GetNamedSecurityInfo returns 0 (ERROR_SUCCESS) , which means there is no error in execution of it but SACL still becomes 0x00000000. Does anyone know what the problem is?

int GetFileIntegrityLevel()
{
    DWORD integrityLevel = SECURITY_MANDATORY_UNTRUSTED_RID;
    PSECURITY_DESCRIPTOR pSD = NULL;
    PACL acl = 0;
    int dw = 0; 
        GetNamedSecurityInfoA("C:\\8.docx", SE_FILE_OBJECT, SACL_SECURITY_INFORMATION,  0, 0, 0, &acl, &pSD));
    {
        if (0 != acl && 0 < acl->AceCount)
        {
            SYSTEM_MANDATORY_LABEL_ACE* ace = 0;
            if (GetAce(acl, 0, reinterpret_cast<void**>(&ace)))
            {
                SID* sid = reinterpret_cast<SID*>(&ace->SidStart);
                integrityLevel = sid->SubAuthority[0];
            }
        }

        PWSTR stringSD;
        ULONG stringSDLen = 0;

        ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, ACCESS_SYSTEM_SECURITY, &stringSD, &stringSDLen);

        if (pSD)
        {
            LocalFree(pSD);
        }
    }

    if (integrityLevel == 0x0000)
        return 0;
    else if (integrityLevel == 0x1000)
        return 1;
    else if (integrityLevel == 0x2000)
        return 2;
    else if (integrityLevel == 0x3000)
        return 3;
    else if (integrityLevel == 0x4000)
        return 4;
    else
        return -1;
}


int main()
{

    HANDLE curProcess = GetCurrentProcess();

    TOKEN_PRIVILEGES tp;
    LUID sdv;

    HANDLE hToken = 0;
    OpenProcessToken(curProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_READ | TOKEN_QUERY, &hToken);

    LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &sdv);

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = sdv;  
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), (PTOKEN_PRIVILEGES)NULL, 0);


    int i = GetFileIntegrityLevel();

    printf("%d\n", i);



    printf("%d\n", i);
    CloseHandle(curProcess);
    std::cin.get();
}
1

There are 1 best solutions below

6
On

you need use not SACL_SECURITY_INFORMATION but LABEL_SECURITY_INFORMATION

example code:

ULONG GetFileIntegrityLevel(PCWSTR fileName, PULONG pil)
{
    PACL Sacl;
    PSECURITY_DESCRIPTOR pSD;
    *pil = SECURITY_MANDATORY_MEDIUM_RID;// default LABEL

    ULONG err = GetNamedSecurityInfoW(fileName, SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, 0, 0, 0, &Sacl, &pSD);

    if (!err)
    {
        if (Sacl)
        {
            union {
                PVOID Ace;
                PSYSTEM_MANDATORY_LABEL_ACE pLabel;
                PACE_HEADER pHeader;
            };

            err = ERROR_GEN_FAILURE;

            ACL_SIZE_INFORMATION asi;

            if (GetAclInformation(Sacl, &asi, sizeof(asi), AclSizeInformation))
            {
                PSID Sid;

                union {
                    PUCHAR pc;
                    PULONG pl;
                };

                static SID_IDENTIFIER_AUTHORITY LabelAuth = SECURITY_MANDATORY_LABEL_AUTHORITY;

                switch (asi.AceCount)
                {
                case 1:
                    if (GetAce(Sacl, 0, &Ace))
                    {
                        if (pHeader->AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
                        {
                            Sid = &pLabel->SidStart;

                            if (pc = GetSidSubAuthorityCount(Sid))
                            {
                                if (*pc == 1 && !memcmp(&LabelAuth, GetSidIdentifierAuthority(Sid), sizeof(SID_IDENTIFIER_AUTHORITY)))
                                {
                                    if (pl = GetSidSubAuthority(Sid, 0))
                                    {
                                        *pil = *pl;
                case 0:
                                        err = ERROR_SUCCESS;
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }

        LocalFree(pSD);
    }

    return err;
}

despite that SYSTEM_MANDATORY_LABEL_ACE_TYPE is located in SACL - SACL_SECURITY_INFORMATION not return this ACE - it filter SACL and remove this ACE type from output. only LABEL_SECURITY_INFORMATION return this ACE type - SACL also filtered, and removed all ACEs, except this type. if we want got not filtered SACL as is - need use both flags - LABEL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION.

in most case files/folders have no mandatory label at all. in this case by default - SECURITY_MANDATORY_MEDIUM_RID assumed. so algorithm is next - we query label with LABEL_SECURITY_INFORMATION

  • if file have no SACL at all - we got NULL Sacl in output - so by default SECURITY_MANDATORY_MEDIUM_RID
  • if file have SACL but without label - we got empty Sacl in output (Sacl != NULL && AceCount == 0) - again SECURITY_MANDATORY_MEDIUM_RID by default
  • if file have mandatory label - we must got Sacl with AceCount == 1 - need extract RID form this ACE

also for SACL_SECURITY_INFORMATION

Right required to query: ACCESS_SYSTEM_SECURITY

Right required to set: ACCESS_SYSTEM_SECURITY

To read the SACL from the security descriptor, the calling process must have been granted ACCESS_SYSTEM_SECURITY access when the handle was opened. The proper way to get this access is to enable the SE_SECURITY_NAME privilege in the caller's current token, open the handle for ACCESS_SYSTEM_SECURITY access, and then disable the privilege

but for got LABEL_SECURITY_INFORMATION we not need have/enable any privileges

Right required to query: READ_CONTROL

Right required to set: WRITE_OWNER