Impact of Least Privilege in System Services


Of all security changes in Vista, UAC with its spit token and MIC is for obvious reasons getting most attention. But there are a lot of other areas that have been tightened up for security reasons and we keep finding new ones that impact customers. One of them is detailed in the document on service changes in Vista. The specific session is called Running with Least Privilege.


In Vista you can have NT services explicitly have only the privileges they need. You can view them with “sc qpriv” or just go to the registry (HKLM\SYSTEM\CurrentControlSet\Services under RequiredPrivileges). This is a good thing because you no longer have to get all the other privileges that for example Local System has if you only need one or two. For example “sc qprivs rpcss” will give you only three privileges on Vista.


As with pretty much any change, there are impacts. For example, if your MSI package had a custom action (CA) that was assuming the Windows Installer service had the SeBackupPrivilege, you will be unpleasantly surprised. Checking it with “sc qpriv msiserver” shows that SeBackupPrivilege is no longer there. This was done to reduce the attack surface of the Windows Installer service.


Let us know if this or another service missing a privilege is impacting you.


Thanks to Christopher for pointing this out.


Maarten

Comments (6)

  1. Antti Nivala says:

    The lack of SeBackupPrivilege prevents our M-Files software from installing on Vista (upgrade from one version to another fails). The impact to us is severe and it seems it will require major rework to get the installation system run on Vista given this limitation. Are you sure that this limitation is worth adding given that it will prevent the installation of some applications on Vista? Ours surely cannot be the only one.

    Our MSI package has a CA that requires SeBackupPrivilege because it calls RegLoadKey. We call RegLoadKey because during an upgrade (not related to MSI upgrade), we need to migrate each user’s settings in the registry from the old version’s key to the new version’s key. After copying the settings, we uninstall the old version, which deletes the settings from each user’s registry hive in the same way.

    Is there any way our MSI package could modify the other users’ HKCU settings in Vista?

    Any chance on you allowing RegLoadKey in CAs, perhaps in some other way than putting SeBackupPrivilege back?

  2. prsTM says:

    My service is trying to create a pipe that’s writeable by any user account. I’ve tried to set the security attributes two ways. Both of them work fine on XP, but on Vista, the user process gets an Access Denied on its CreateFile call.

    Any help you-all can provide would be most welcome.

    The first method I used was fairly straightforward:

    SECURITY_DESCRIPTOR sd;

    ::InitializeSecurityDescriptor( &sd,SECURITY_DESCRIPTOR_REVISION );

    ::SetSecurityDescriptorDacl( &sd,TRUE, (PACL)NULL,FALSE );

    SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES),

    &sd,

    FALSE };

    And the second one more complex, provided by another developer:

    CSharedSecurityDescriptor sd;

    if ( !sd.Init() )

    {

    DWORD dw = ::GetLastError();

    ReportMessage("Could not init security descriptor", true);

    return 1;

    }

    SECURITY_ATTRIBUTES sa = {sizeof sa, &sd, FALSE};

    class CSharedSecurityDescriptor : public SECURITY_DESCRIPTOR

    {

    public:

         CSharedSecurityDescriptor()

         {

               Dacl = NULL;

         }

     bool Init(void)

         {

               if ( !InitializeSecurityDescriptor( this, SECURITY_DESCRIPTOR_REVISION ) )

               {

                     return false;

               }

               CWellKnownSID2 sidUsers(DOMAIN_ALIAS_RID_USERS);

               CWellKnownSID2 sidAdmins(DOMAIN_ALIAS_RID_ADMINS);

               DWORD nACLSize = sizeof(ACL) + ((sizeof(ACCESS_ALLOWED_ACE) – sizeof(DWORD) + sizeof(CWellKnownSID2)) * 3);

               PACL pACL = (PACL)LocalAlloc(LPTR, nACLSize);

               if ( pACL )

               {

                     if ( InitializeAcl( pACL, nACLSize, ACL_REVISION) )

                     {

                           //do not use the EX version – ACE inheritance is not required.

                           if ( AddAccessAllowedAce( pACL, ACL_REVISION, GENERIC_ALL, &sidUsers ) &&

                                 AddAccessAllowedAce( pACL, ACL_REVISION, GENERIC_ALL, &sidAdmins ) )

                           {

                                 if ( SetSecurityDescriptorDacl( this, TRUE, pACL, FALSE ) )

                                 {

                                       return true;

                                 }

                           }

                     }

                     LocalFree( pACL );

     SetSecurityDescriptorDacl( this, TRUE, NULL, FALSE );    //set NULL DACL – allow all

     return false;

               }

               return TRUE == SetSecurityDescriptorDacl( this, TRUE, NULL, FALSE );    //set NULL DACL – allow all

         }

         ~CSharedSecurityDescriptor()

         {

               BOOL bPresent = FALSE, bDefaulted = TRUE;

               PACL pACL = NULL;

               if ( GetSecurityDescriptorDacl( this, &bPresent, &pACL, &bDefaulted ) )

               {

                     if ( bPresent && !bDefaulted && pACL )

                     {

                           ::LocalFree( pACL );

                     }

               }

         }

    protected:

         struct CWellKnownSID2 : public SID //a SID with 2 sub authorities

         {

               CWellKnownSID2( DWORD dwSecondSubAuth )

               {

                     SecureZeroMemory( IdentifierAuthority.Value, sizeof(IdentifierAuthority.Value) );

                     Revision = SID_REVISION;

                     SubAuthorityCount = 2;

                     IdentifierAuthority.Value[5] = 5; //SECURITY_NT_AUTHORITY {0,0,0,0,5}

                     SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;

                     m_dwSecondSubAuth = dwSecondSubAuth;

               };

               DWORD m_dwSecondSubAuth;

         };

    };

  3. Peter.Delgado says:

    I suggest that you simply add the group Everyone or some common group (more secure) to the dacl as follows (note the use of the ATL security classes which simplifies the procedure)

    -Pete

    CDacl daclPerm;

    CSid sidEveryone = CreateWellKnownLocalSid ( WinWorldSid );

    daclPerm.AddAllowedAce ( sidEveryone, GENERIC_ALL );

    CSecurityDesc sd;

    sd.SetDacl ( daclPerm );

    CSecurityAttributes sa ( sd );

    m_hPipe =  ::CreateFile ( m_PipeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &sa, OPEN_EXISTING, 0, NULL) ;

    In addition, the code for the function CreateWellKnownLocalSid is as follows:

    CSid CreateWellKnownLocalSid ( WELL_KNOWN_SID_TYPE WellKnownSidType )

    {

    CSid sidRet;

    DWORD dwSize = SECURITY_MAX_SID_SIZE;

    PSID pSid = ::_alloca ( dwSize );

    if ( ::CreateWellKnownSid ( WellKnownSidType, NULL, pSid, &dwSize) )

    {

    sidRet = CSid (reinterpret_cast<const SID*>( (pSid ) ) );

    }

    return sidRet;

    }

  4. brianwa84 says:

    Echoing Antti, our software uses RegLoadKey to read/write to each user’s registry on install/uninstall. Losing SeBackupPrivilege makes it so that our installer/uninstaller can only successfully install/uninstall for the current user, even when MSI is running us from the LocalSystem account. I agree that numerous applications are likely to use RegLoadKey to perform some kind of per-user installation, and losing it will make MSI a much less useful installation mechanism.

  5. brianwa84 says:

    Are there any changes to give any privileges back to the windows installer service, or will a better approach be to hack around it and/or use nsis or installshield or some other installation platform?

  6. Apart from the feature work that we did in Windows Installer 4.5, we made a few changes to Windows Installer

Skip to main content