MSI Error “The computer must be trusted for delega

2019-03-11 06:26发布

We have an MSI based installer that recently stopped working on a Windows 2008 R2 environment. The installer is copied over to the target computer using the \\servername\c$\ admin UNC shares and then is remotely executed using the create method on the WMI Win32_Process class. The remote execution now fails with the following error message in the Event Viewer:

The description for Event ID 10837 from source MsiInstaller cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.

If the event originated on another computer, the display information had to be saved with the event.

The following information was included with the event:

Product: OUR PRODUCT NAME -- The requested operation cannot be completed. The computer must be trusted for delegation and the current user account must be configured to allow delegation.

After searching it looks like this is caused by a recently released security patch for Windows Installer. When I uninstall KB2918614 the installer starts working again, and if I reinstall KB2918614 the MSI stops working again.

The error message indicates that to solve the issue we would have to have a Domain Administrator edit the target computer using Active Directory Users and Computers to allow delegation, however the MSI is NOT using any remote resources, so I don't see why this is required. The same MSI and remote execution process works fine on Windows Server 2012, so I wonder if this is an issue with the patch for 2008 R2.

Are there any other ways to get around this error message?

UPDATE: This doesnt appear to be an issue with the WMI remote execution, as it also occurs when we try to install the MSI remotely using Powershell, WinRM, and the Invoke-Commmand -ComputerName TargetComputer ... cmdlet. There is a change in the way the Windows Installer on 2008 R2 works after installing KB2918614 that now prevents the custom action from completing it's task.

9条回答
ら.Afraid
2楼-- · 2019-03-11 06:29

I also encounter the issue. I got powershell script to install MSI on remote machines (using Invoke-Command cmdlet and provide the credential along with the script), but suddenly it failed to install MSI which I suppose also from this security patch.
After run the MSI installation file manually on target machine using the domain account (from remote desktop), suddenly the powershell script can run the MSI installation using domain account, but still failed to install if I used target machine local admin account.
I prefer to add this as a comment, but I don't have enough rep to do that. If the other has any solution or explanation for this I'd love to know that too. Thanks.

查看更多
再贱就再见
3楼-- · 2019-03-11 06:30

From what I understand,

With KB2918614, MS have apparently tried to fix something in the Windows Installer Service.

New stuff:

  • They are creating a file by name "SourceHash{PRODUCT-GUID}" under %windir%\Windows\Installer. This is done for every product installed on the machine(with KB2918614 already installed).
  • SECREPAIR- They are computing 'Stored Hash Value' and 'Current Hash' for a given MSI.

Error:

  1. And, in this comparison, for some reason, these mismatch! (Found these in the MSI verbose logs).

  2. Once this fails, it looks for Machine policy value 'AlwaysInstallElevated' User policy value 'AlwaysInstallElevated'

  3. Now, if you are running a silent install "qn", this error is thrown: MSI_LUA: Elevation prompt disabled for silent installs.

  4. Removing silent install cmdline option for msiexec- ex., "qr" or "qb", will throw a UAC prompt. (which most likely will not be the expected behavior).

Additional Info:

My MSI is ivkoded through a bootstrapper exe. But, it doesn't really matter. Even a manual call to msiexec through cmd line behaves the same way.

Any inputs/solutions, anyone?

查看更多
Animai°情兽
4楼-- · 2019-03-11 06:33

If you are executing through psexec, just adding the -s argument also resolves the error. Then it is ran as the remote system user and UAC is not required.

查看更多
祖国的老花朵
5楼-- · 2019-03-11 06:37

Here is my automatic way of utilizing the registry whitelist work around mentioned on Microsoft's site.

Now, before I run my install command against a remote machine, I look at the MSI and extract the product code with Get-ProductCodeFromMSI, and then use Add-GuidToWhitelist to add each GUID to the list on that computer. Here's an example:

$guids = Get-ChildItem -Path D:\somefolder -filter "*.msi" -recurse | % {Get-ProductCodefromMSI $_.FullName}
Add-GUIDtoWhiteList -computername "SomeServer" -GUIDs $guids

Before doing that, each machine can be tested and repaired for the workaround using Test-SecureRepairPolicy and Repair-SecureRepairPolicy, respectively.

Get-ProductCodeFromMSI will require the DLL referenced to be placed somewhere and unblocked - this DLL can be retrieved from the Wix toolset.

Code for the functions I reference is here:

Function Test-SecureRepairPolicy{
    param (
        [Parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][string[]]
        # Specifies the computer name to connect to
        $ComputerName
    )

    Process {
        foreach ($Computer in $ComputerName)
        {
            #Open Remote Base
            $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer)
            #Get Windows key
            $subkey = $reg.OpenSubKey("SOFTWARE\Policies\Microsoft\Windows")
            $subkeynames = $subkey.GetSubKeyNames()
            if (($subkeynames | Measure-Object).Count -lt 1){
                return New-Object -type PSObject -Property @{
                    Success = $False
                    Note = "Can not open base key"
                    ComputerName = $Computer
                }
            }
            if ($subkeynames -notcontains "Installer"){
                return New-Object -type PSObject -Property @{
                    Success = $False
                    Note = "Can not locate installer subkey"
                }
            }
            $subkey.Close();$subkey = $null
            $subkey = $reg.OpenSubKey("SOFTWARE\Policies\Microsoft\Windows\Installer")
            $subkeynames = $subkey.GetSubKeyNames()
            if ($subkeynames -notcontains "SecureRepairWhitelist"){
                return New-Object -type PSObject -Property @{
                    Success = $False
                    Note = "Can not locate repairlist subkey"
                    ComputerName = $Computer
                }
            }
            $repairvalue = $subkey.GetValue("SecureRepairPolicy")
            if ($repairvalue -ne 2){
                return New-Object -type PSObject -Property @{
                    Success = $False
                    Note = "SecureRepairPolicy is incorrect"
                    ComputerName = $Computer
                }
            }
            $subkey.Close();$subkey = $null;$reg.Close();$reg = $null
            return New-Object -type PSObject -Property @{
                Success = $True
                Note = "SecureRepairPolicy structure is in place"
                ComputerName = $Computer
            } 
        }
    }
}

Function Repair-SecureRepairPolicy{
    param (
        [Parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][string[]]
        # Specifies the computer name to connect to
        $ComputerName

    )
    Begin{
        Function Add-RemoteRegistryKey($Computer,$Parent,$Name){
            $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer)
            $subkey = $reg.OpenSubKey($Parent, $true)
            $subkey.CreateSubKey($Name)
            $subkey.Close();$subkey = $null;$reg.Close();$reg = $null
        }
        Function Add-InstallerKey($Computer){
           Add-RemoteRegistryKey $Computer "SOFTWARE\Policies\Microsoft\Windows" "Installer" 
        }
        Function Add-RepairPolicy($Computer){
            $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer)
            $subkey = $reg.OpenSubKey("SOFTWARE\Policies\Microsoft\Windows\Installer", $true)
            $subkey.SetValue("SecureRepairPolicy",2, "DWORD")
            $subkey.Close();$subkey = $null;$reg.Close();$reg = $null
        }
        Function Add-WhitelistKey($Computer){
            Add-RemoteRegistryKey $Computer "SOFTWARE\Policies\Microsoft\Windows\Installer" "SecureRepairWhitelist"
        }

    }
    Process {
        foreach ($Computer in $ComputerName)
        {
            $audit = Test-SecureRepairPolicy $computer
            if ($audit.Success){
                Write-Output "Repair whitelist keys setup.  No repair being performed."
            }
            else{
                Write-Output "Repair whitelist keys not setup.  Attempting to resolve"
                 if ($audit.Note -match "Can not open base key"){
                    Write-Error "Unable to open computer's registry key"
                    return
                 }
                 if ($audit.Note -match "Can not locate installer subkey"){
                    Add-Installerkey $Computer
                    Add-RepairPolicy $Computer
                    Add-WhitelistKey $Computer
                 }
                 if ($audit.Note -match "Can not locate repairlist subkey"){
                    Add-RepairPolicy $Computer
                    Add-WhitelistKey $Computer
                 }
                 if ($audit.Note -match "Can not locate repairlist subkey"){
                    Add-RepairPolicy $Computer
                 }
                 Write-Output "Showing new audit"
                 Test-SecureRepairPolicy $computer
            }
        }
    }
}

Function Add-GUIDtoWhiteList{
    param (
        [Parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][string[]]
        # Specifies the computer name to connect to
        $ComputerName,
        [Parameter(mandatory=$true)][string[]]
        # Specifies the GUID(s) to add.
        $GUIDs
    )

    Process {
        foreach ($Computer in $ComputerName)
        {
            #Open Remote Base
            $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer)
            $subkey = $reg.OpenSubKey("SOFTWARE\Policies\Microsoft\Windows\Installer\SecureRepairWhitelist", $true)
            foreach($GUID in $GUIDs){
                $subkey.SetValue($GUID,"", "String")
            }
            $subkey.Close();$subkey = $null;$reg.Close();$reg = $null
        }
    }
}

Function Get-ProductCodefromMSI ($msi){
    [Reflection.Assembly]::LoadFrom("D:\scripts\lib\Microsoft.Deployment.WindowsInstaller.dll") | out-null
    (New-Object -TypeName Microsoft.Deployment.WindowsInstaller.Database -ArgumentList $msi).ExecuteQuery("SELECT Value FROM Property WHERE Property = 'ProductCode'")
}
查看更多
Viruses.
6楼-- · 2019-03-11 06:43

This is the word from the MS Enterprise Support folks.

Apparently they are not aware of any fix to this. At-least as of now. All they are saying that this KB is to fix a security loophole. I don't understand what kind of a security fix this is- one that allows a Fresh Install without an UAC prompt, but throws an UAC prompt only for the Upgrade.

Workaround 1: Distributing hash.

Capture the Hash file* in one machine and distribute them to other machines. Hash files are created under “%windir%\installer” directory. The naming convention is as follows: “SourceHash * This file is created only when a Product is installed with KB2918614 installed on the machine.This directory is hidden. Open cmd prompt using 'run as administrator'. Traverse to this path and open the folder using "explorer ." command. [I couldn't solve the issue using this approach- may be because accessing this directory requires administrator privileges which the Windows Installer itself might not have]

Workaround 2: Whitelisting.

Only if you trust the application that it is always digitally signed and doesn't contain anything malicious(even in the future).

Step 1: Enable Whitelisting

Under Key “HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer”, create a DWORD: “SecureRepairPolicy” and set its Value to 2.

Step 2: Add the application to the whitelist

Create a new key “SecureRepairWhitelist” under "HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer” and create StringValues with the product codes(Including flower brackets {}) of the product.

... Sadly though, both these workarounds need admin privileges!

查看更多
时光不老,我们不散
7楼-- · 2019-03-11 06:43

Response from Microsoft: This security update resolves a privately disclosed vulnerability in Microsoft Windows. The vulnerability could allow elevation of privilege if an attacker runs a specially crafted application that attempts to repair a previously-installed application. An attacker must have valid logon credentials and be able to log on locally to exploit this vulnerability.

Workaround if you have problems with repairing application:

  1. Uninstall the application and reinstall it with the security update installed. (sourcehash file generated with security update)

  2. Manually copy the sourcehash file to c:\windows\installer folder. As the sourcehash file is generated based on the application files, the sourcehash file generated on computer A can be used on computer B.

  3. http://happysccm.com/kb2918614-uac-gate/ - commands to uninstall it.

查看更多
登录 后发表回答