2
votes

I'm using ConvertStringSecurityDescriptorToSecurityDescriptor to create a security descriptor that I can then use with CreateFile as it is much easier and much more readable.

My intent is for the file to be fully controllable by its owner/creator and readable only by elevated processes.

I thus came up with the following SSDL string:

  SSDL :=
    'O:'+ SIDAsString  +                   // owner is user
    'D:' +                                 // Discretionary ACL
    'P' +                                  // protected
    '(A;NP;FA;;;' + SIDAsString + ')' +    // Full control to owner
    // Read only access to administrators 
    '(A;NP;FR;;;LA)' +
    '(A;NP;FR;;;BA)';

SIDAsString contains a valid SID, such as S-1-5-18 for instance.

ConvertStringSecurityDescriptorToSecurityDescriptor returns a valid security descriptor and the file gets created with the rights that I expected.

However, elevated processes (such as an uninstaller for instance) cannot read the file, they get an access denied error. If the process that tries to read the file is started via the run as administrator option, it receives access as expected.

I tried looking for the elevated user SID, but I could not find any mention of it, which leads me to believe that there is no such thing.

Short of giving read access to everyone, is there a way to specify a SSDL string that gives read access to a process running with elevated privileges?

1
Elevation does not change a user's SID or group associations, only its token permissions. The same user can run elevated and non-elevated processes. AFAIK, you can't use a Security Descriptor to grant/revoke access based on elevation status. I think you need to read up on what elevation actually is and how it works. Perhaps the reading app can try enabling the SE_BACKUP_NAME permission for itself and then open the file with the FILE_FLAG_BACKUP_SEMANTICS flag enabled. That might grant the read access you are looking for. - Remy Lebeau
@RemyLebeau - when process run not elevated under UAC - he have Administrators (S-1-5-32-544) but with SE_GROUP_USE_FOR_DENY_ONLY attribute. when process started elevated - he have Administrators (S-1-5-32-544) with SE_GROUP_ENABLED - so really exist different with group associations. if we let access only for Administrators (S-1-5-32-544) - elevated process will be have access but not elevated - no - RbMm
"However, elevated processes cannot read the file" - vs "If the process started via the run as administrator option, it receives access as expected." - so can elevated process read file or not ? and (A;NP;FR;;;LA) or may be need (A;NP;FRFX;;;LA) for enable execute access on file too ? - RbMm
@RbMm: SE_GROUP_USE_FOR_DENY_ONLY and SE_GROUP_ENABLED are not users/groups that a security descriptor can refer to. They are simply token attributes that control how SIDs are compared to a security descriptor's ACEs. So you still cannot tailor a security descriptor to grant/reject access based on the elevated status of a user/group using attributes. - Remy Lebeau
@RemyLebeau - "you can't use a Security Descriptor to grant/revoke access based on elevation status." - this not true. simply example - c:\windows folder - elevated user can create/change files in this folder when not elevated can not. because Administrators have write permission for write, but not elevated user have this SID in token, but it used for Denny only - RbMm

1 Answers

0
votes

I tried looking for the elevated user SID

this SID is S-1-5-32-544 ( Administrators ). every process have token, token containing TOKEN_GROUPS which containing SID_AND_ATTRIBUTES array. for same admin user when it started elevated or not elevated - this array is different. both (elevated and not elevated) admins have S-1-5-32-544 but with different attributes ! elevated admin have it with SE_GROUP_ENABLED but not elevated (restricted) admin with SE_GROUP_USE_FOR_DENY_ONLY

A SID with this attribute is a deny-only SID. When the system performs an access check, it checks for access-denied ACEs that apply to the SID, but it ignores access-allowed ACEs for the SID.

so this is key point - we need create SD with DACL where we enable appropriate access to S-1-5-32-544 ( Administrators ) only (and say to system too)- as result elevated process will be have access to file, when not elevated - no.

demo: we create SD with next access in DACL rules:

001F01FF S-1-5-18 SYSTEM
001200A9 S-1-5-32-544 Administrators

so all access to SYSTEM and read/execute to Administrators - file with this DACL not elevated process (say notepad) can not even open for read-only. when elevated notepad - can open and read. but cannot write or delete

note: for set SYSTEM as owner we need SE_RESTORE_PRIVILEGE

void TestX()
{
    SECURITY_ATTRIBUTES sa = { sizeof(sa) };

    if (ConvertStringSecurityDescriptorToSecurityDescriptor(
        L"O:SYD:P(A;NP;FA;;;SY)(A;NP;FRFX;;;BA)", 
        SDDL_REVISION_1, &sa.lpSecurityDescriptor, 0))
    {
        HANDLE hToken;
        if (OpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
        {
            static ::TOKEN_PRIVILEGES tp = {
                1, { { { SE_RESTORE_PRIVILEGE }, SE_PRIVILEGE_ENABLED|SE_PRIVILEGE_ENABLED_BY_DEFAULT } }
            };
            AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), 0, 0);
            CloseHandle(hToken);
        }

        HANDLE hFile = CreateFile(L"c:\\windows\\1.txt", FILE_GENERIC_WRITE, 0, &sa, CREATE_NEW, 0, 0);

        if (hFile != INVALID_HANDLE_VALUE)
        {
            ULONG cb;
            WriteFile(hFile, "1234567890", 10, &cb, 0);
            CloseHandle(hFile);
        }

        LocalFree(sa.lpSecurityDescriptor);
    }
}

you can test how elevated/not elevated process (say notepad.exe) open this file.