问题 由KB2918614引起的MSI错误“计算机必须受信任以进行委派”


我们有一个基于MSI的安装程序,最近停止在Windows 2008 R2环境中工作。使用安装程序将安装程序复制到目标计算机 \\servername\c$\ admin UNC共享然后使用create方法远程执行 WMI Win32_Process类。远程执行现在失败,并在事件查看器中显示以下错误消息:

来自源MsiInstaller的事件ID 10837的描述不可能   找到。未安装引发此事件的组件   您的本地计算机或安装已损坏。你可以安装   或修复本地计算机上的组件。

如果事件源自另一台计算机,则显示信息   不得不与事件一起得救。

活动中包含以下信息:

产品:我们的产品名称 - 请求的操作不能   完成。必须信任计算机才能授权和使用   必须将当前用户帐户配置为允许委派

搜索后看起来这是由最近发布的 Windows Installer的安全修补程序。当我卸载KB2918614时,安装程​​序再次开始工作,如果我重新安装 KB2918614 MSI再次停止工作。

错误消息表明要解决此问题,我们必须让域管理员使用编辑目标计算机 Active Directory用户和计算机 允许委托,但MSI不使用任何远程资源,所以我不明白为什么这是必需的。相同的MSI和远程执行过程在Windows Server 2012上运行良好,所以我想知道这是否是2008 R2补丁的问题。

有没有其他方法来解决此错误消息?

UPDATE:这似乎不是WMI远程执行的问题,因为当我们尝试使用Powershell,WinRM和远程安装MSI时也会出现这种情况。 Invoke-Commmand -ComputerName TargetComputer ... 小命令。安装KB2918614后,2008 R2上的Windows Installer的工作方式发生了变化,现在阻止自定义操作完成它的任务。


6116
2017-08-29 15:50


起源

我会尝试允许授权,至少作为实验。我怀疑问题不在于MSI访问远程资源,而是与安装的各个部分中的模拟(或不模仿)有关。一个纯粹的猜测,但安装在安装期间在用户帐户和系统帐户之间移动,并且可能在域环境中发生需要委托传递到域控制器或从域控制器传递的事情,无论如何。 - PhilDW
好吧,你实际上是在使用远程资源,该文件来自另一台机器。 Windows知道这一点并将该信息存储在备用NTFS数据流中。在superuser.com上提出有关此问题的问题 - Hans Passant
我们设计了MSI并希望找到一种方法来重写它来为我们的客户解决这个问题。我检查了文件是否被阻止,但它似乎没有安全性:“此文件来自另一台计算机”或文件属性中的“取消阻止”选项。 - Greg Bray
在应用此MS更新后,我们还遇到了远程执行MSI的问题。我今天与一位微软代表进行了交谈,他说这是一个已知的问题。他告诉我他们希望在10月中旬到11月初的时间范围内有一个额外的补丁来解决这个问题。 - ksun
我今天跟进了微软,他们告诉我这里找到的解决方案可以解决这个问题: support2.microsoft.com/kb/3000988。但是,我在下面的答案中看到,这是低估的。有没有人应用这个补丁并让它不适合他们? - ksun


答案:


据我所知,

对于KB2918614,MS显然试图修复Windows Installer服务中的某些内容。

新的东西:

  • 他们正在创建一个名为“SourceHash {PRODUCT-GUID}”的文件 %WINDIR%\的Windows \ Installer程序。这是为每个安装的产品完成的 在机器上(已安装KB2918614)。
  • SECREPAIR-他们正在计算给定MSI的“存储哈希值”和“当前哈希值”。

错误:

  1. 并且,在这种比较中,出于某种原因,这些不匹配! (在MSI详细日志中找到这些)。

  2. 一旦失败,它就会寻找     机器策略值'AlwaysInstallElevated'     用户策略值'AlwaysInstallElevated'

  3. 现在,如果您正在运行静默安装“qn”,则会抛出此错误:MSI_LUA:已禁用提升安装的提升提示。

  4. 删除msiexec- ex。,“qr”或“qb”的静默安装cmdline选项将抛出UAC提示符。 (这很可能不是预期的行为)。

附加信息:

我的MSI通过bootstrapper exe进行了ivk。但是,这并不重要。即使通过cmd行手动调用msiexec的行为也是一样的。

任何输入/解决方案,任何人?


5
2017-09-11 06:23





这是来自MS Enterprise支持人员的话。

显然他们并不知道对此有任何解决方法。至少截至目前。 他们只是说这个KB是为了修复安全漏洞。 我不明白这是什么类型的安全修复程序 - 允许在没有UAC提示的情况下进行全新安装,但仅为升级引发UAC提示。

解决方法1:  分发哈希。

在一台计算机中捕获哈希文件*并将其分发到其他计算机。 散列文件在“%windir%\ installer”目录下创建。命名约定如下:“SourceHash *仅当安装了产品并且机器上安装了KB2918614时才会创建此文件。此目录已隐藏。使用“以管理员身份运行”打开cmd提示符。遍历此路径并使用“资源管理器”打开文件夹。命令。 [我无法使用此方法解决问题 - 可能是因为访问此目录需要Windows安装程序本身可能没有的管理员权限]

解决方法2:  白名单。

只有当您信任该应用程序时,它始终经过数字签名并且不包含任何恶意内容(即使将来)。

第1步:启用白名单

在Key“HKLM \ SOFTWARE \ Policies \ Microsoft \ Windows \ Installer”下,创建一个DWORD:“SecureRepairPolicy”并将其值设置为2。

第2步:将应用程序添加到白名单

在“HKLM \ SOFTWARE \ Policies \ Microsoft \ Windows \ Installer”下创建一个新密钥“SecureRepairWhitelist”,并使用产品的产品代码(包括花括号{})创建StringValues。

......遗憾的是,这两种解决方法都需要管理员权限!


3
2017-10-09 10:51



谢谢DebugBreak先生!这真的让我有点激动。显然补丁正在修改,所以我们(希望)不必搞砸这些东西。 - slashp
欢迎。是的,这对开发人员来说非常糟糕。最终用户可以某种方式解决问题。一个建议:如果可行:遇到升级方案时,卸载产品并进行全新安装。 - DebugBreak
我尝试分发哈希,但MSI正在删除它并试图重新创建它,在娱乐过程中发生了失败。我也无法将白名单工作。安装程序密钥丢失了,然后我尝试使用psexec -s,这很有用。白名单在msdn上列为解决方法: support.microsoft.com/en-us/kb/2918614 - curlyhairedgenius


这是我使用Microsoft网站上提到的注册表白名单工作的自动方式。

现在,在我对远程计算机运行安装命令之前,我查看MSI并使用Get-ProductCodeFromMSI提取产品代码,然后使用Add-GuidToWhitelist将每个GUID添加到该计算机上的列表中。这是一个例子:

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

在此之前,可以分别使用Test-SecureRepairPolicy和Repair-SecureRepairPolicy对每台计算机进行测试和修复以解决此问题。

Get-ProductCodeFromMSI将要求引用的DLL放在某处 并且畅通无阻  - 可以从Wix工具集中检索此DLL。

我引用的函数代码如下:

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'")
}

3
2017-11-12 17:09





我也遇到了这个问题。我有PowerShell脚本在远程机器上安装MSI(使用Invoke-Command cmdlet并提供凭证和脚本),但突然无法安装MSI,我想也是从这个安全补丁。
使用域帐户(从远程桌面)在目标计算机上手动运行MSI安装文件后,powershell脚本突然可以使用域帐户运行MSI安装,但如果我使用目标计算机本地管理员帐户,仍然无法安装。
我更喜欢将其添加为评论,但我没有足够的代表来做到这一点。如果对方有任何解决方案或解释,我也很想知道。谢谢。


1
2017-09-03 03:47





这与\ windows \ installer目录下的SourceHash {product-code}文件有关。 这个文件可以用Orca打开,你可以阅读内容。它包含文件名,哈希算法说明符和哈希。在Windows 2k3上,此哈希是base64ed sha256哈希,最后一个字节已更改。

如果你 重命名产品的SourceHash文件,我发现升级工作,然后生成一个新的SourceHash文件。然后,您可以区分两个源哈希文件。在我正在调查的情况下,当你对两个文件进行区分时,只有原始msi列出的哈希值不同。 成功升级后,源哈希文件中列出的新msi的哈希值将与安装源的哈希值相匹配。破碎的sourcehash文件显然是从修改后的/不同的源MSI生成的,尽管我还无法识别哪个。


1
2017-09-11 09:23





我也有同样的问题。无法使用Invoke-Command PoSH安装MSI。我发现,如果我在服务器本地服务器上安装任何MSI,用于Invoke-Command的同一帐户,问题就解决了,Invoke-Command开始像往常一样工作。


1
2017-10-09 11:14





来自Microsoft的回复: 此安全更新可解决Microsoft Windows中一个秘密披露的漏洞。如果攻击者运行试图修复以前安装的应用程序的特制应用程序,则该漏洞可能允许特权提升。攻击者必须拥有有效的登录凭据,并且能够在本地登录才能利用此漏洞。

如果修复应用程序时遇到问题,请解决此问题:

  1. 卸载应用程序并在安装了安全更新的情况下重新安装它。 (使用安全更新生成的sourcehash文件)

  2. 手动将sourcehash文件复制到c:\ windows \ installer文件夹。由于sourcehash文件是基于应用程序文件生成的,因此计算机A上生成的sourcehash文件可以在计算机B上使用。

  3. http://happysccm.com/kb2918614-uac-gate/  - 卸载它的命令。


0
2017-09-09 10:57



请在答案中包含所需的命令。允许链接回来获取更多信息,但不披露与另一方的直接链接时不赞成。但要确保每个答案本身都是完全自包含的。 - EWit