对强制执行了 Windows Defender 应用程序控制 (WDAC) 的基础结构提供扩展支持

Windows Admin Center 支持在平台级别管理强制执行了 Windows Defender 应用程序控制 (WDAC) 的基础结构。 详细了解如何在 Windows Admin Center 中管理强制执行了 WDAC 的基础结构

在平台级别支持此管理并不意味着为 Windows Admin Center 生成的扩展也默认支持对强制执行了 WDAC 的基础结构进行管理。 本指南概述了对一项扩展的要求,该扩展用于支持对强制执行了 WDAC 的基础结构进行管理。

扩展结构要求

若要管理强制执行了 WDAC 的基础结构,Windows Admin Center 必须以特定方式引入并运行 PowerShell 脚本,以遵循最佳安全做法。 若要确保扩展的脚本正确运行,应确保扩展符合以下要求。

所有 PowerShell 脚本均须存储在同一个文件中

根据以往情况,WAC 扩展的开发人员可能会选择将自定义 PowerShell 代码作为字符串包含在其扩展 manifest.json 文件中。 例如,有人可能会选择通过在“script”属性中提供 PowerShell 脚本来定义工具扩展可见性的条件。 若要使 PowerShell 脚本与 WDAC 兼容,须对其进行签名。 而字符串无法进行签名。

若要确保满足此要求,请执行以下步骤:

  1. 标识 manifest.json 文件中的任何 PowerShell 脚本。
  2. 在 manifest.json 文件中定义任何脚本内容后,删除脚本内容并将其存储在扩展的 resources/scripts 目录中的 .ps1 文件中。 扩展清单中的脚本代码现在遵循与其他 Windows Admin Center PowerShell 相同的规则。
  3. 将扩展清单中的 conditions 属性更新为以下格式:
    "conditions": [
        {
            "powerShell": {
                "command": "Script-File-Name",
                "module": "powerShellModuleName",
                "script": "Your script text goes here."
            }
        }
    ]
    
    扩展清单中已存在 PowerShell 模块名称。 它在清单中的值和在 PowerShell 字段中的值必须匹配。
  4. 确定任何其他动态创建 PowerShell 脚本的位置。 通过使用字符串串联来动态创建 PowerShell 脚本,攻击者能够注入要执行的任意 PowerShell 脚本。 此方法可绕过针对运行空间受限的远程用户强制实施的限制。 它还可针对使用用户输入生成 PowerShell 脚本并执行它的任何应用程序实现标准命令注入。

使用字符串串联创建的脚本块的示例:

param($UserInputVar)
$DynamicScript = "Get-ChildItem $UserInputVar"
$ScriptBlock = [ScriptBlock]::Create($DynamicScript)
Invoke-Command $ScriptBlock

未使用字符串串联构造的相同脚本块的示例:

param($UserInputVar)
 [ScriptBlock]$ScriptBlock = {
Param($SafeUserInput)
Get-ChildItem $ SafeUserInput
 }
 Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList @($UserInputVar)

# OR, alternatively
param($UserInputVar)
 Invoke-Command -ScriptBlock {
 param(
    [String] $SafeUserInput
 )
Get-ChildItem $SafeUserInput

} -ArgumentList $UserInputVar

脚本文件的构造也不应使用字符串串联。 下面是如何能不构造脚本文件的示例:

$Script=@'
    Get-ChildItem $UserInputVar
'@
$Script = '$ UserInputVar =' + "'$ UserInputVar;"+$Script 
$path = “C:\temp”
$Script | Out-File $path

改为按以下方式构造脚本文件:

Function test {
    param(
        [String] $userInputVar
     )
    Get-ChildItem $UserInputVar
    }
   
    $path = “C:\temp”
    (Get-Command test).ScriptBlock | Set-Content -path $path

所有 PowerShell 代码都必须签名并存储在正确的位置

为支持对强制执行了 WDAC 的基础结构进行管理,Windows Admin Center 实施了更改,其中,扩展的签名的 PowerShell 脚本现在在运行之前会先被传输到 Windows Admin Center 当前连接到的节点。 此外,如前面的要求中所述,强制执行了 WDAC 的基础结构仅运行签名的 PowerShell 脚本。 为符合这些要求,所有 PowerShell 代码都必须签名。 同时,所有 PowerShell 必须位于一致的位置,以便 Windows Admin Center 平台可以找到扩展的签名的模块。

如果扩展存储库不包含一个包含签名的 PowerShell 模块的 powershell-module 目录,则 Windows Admin Center 平台将无法识别可传输代码,相关操作在强制执行了 WDAC 的环境中会失败。

Windows Admin Center gulp build 命令会更新存储库中的 /dist 文件夹,在模块文件夹中生成未签名的 .psd1 和 .psm1 文件。 这些文件需要使用与 WDAC 策略允许列表中的证书匹配的签名证书进行签名。

若要进行此更改,强烈建议创建包含 PowerShell 签名的生成管道。

可以通过以下两种方式之一验证 PowerShell 的格式是否正确:

  1. 安装扩展后,可以(运行 Windows Admin Center 的)在网关计算机上查看 ProgramData\Server Management Experience\UX\modules 目录。 此时应会看到 powershell-module 文件夹和签了名的 PowerShell 模块
  2. 提取扩展的 .nupkg 项目的内容。 其中应包含 powershell-module 文件夹,并该文件夹中应包含签了名的 PowerShell 模块。

在这两种情况下,都可以通过对文件运行 Get-AuthenticodeSignature 命令或右键单击文件本身并验证数字签名来验证 .psd1 和 .psm1 文件本身是否已签名。

使用“powerShellScript”属性的工作项应更新为使用“powerShell命令”属性

Windows Admin Center 平台需要能够确定 PowerShell 命令所属的模块。 由于此要求,使用 powerShellScript 属性指定 PowerShell 命令的工作项会导致错误。

若要减少这种情况,请使用 powerShellCommand 属性和 createCommand 方法形成有效的命令对象。

下面是使用旧方法的工作项的示例:

    const workItem : WorkItemSubmitRequest = {
      typeId: "SampleWorkItem",
      title: "Title",
      powerShellScript: PowerShellScripts.[scriptName],
      successMessage: "Success",
      errorMessage: "Error",
      progressMessage: "In progress..."
    }

下面是使用新方法的同一工作项:

    const workItem : WorkItemSubmitRequest = {
      typeId: "SampleWorkItem",
      title: "Title",
      powerShellCommand: PowerShell.createCommand(PowerShellScripts.[scriptName]),
      successMessage: "Success",
      errorMessage: "Error",
      progressMessage: "In progress..."
    }

确保 PowerShell 脚本在“有限语言”模式下运行

许多 WDAC 策略会强制所有 PowerShell 脚本在“有限语言”模式下运行。 若要在整个 Windows Admin Center 中维持完整功能,应确保扩展中的所有脚本都遵循以下最佳做法:

  1. 如果使用 PowerShell 模块导出脚本文件,则这些文件必须按名称显式导出函数,且不使用通配符。 此要求是为了防止无意中公开可能不打算公开的帮助程序函数。
  2. 对脚本文件执行 Dot Source 会将该脚本中的所有函数、变量、别名引入当前范围。 此功能可阻止受信任的脚本经由 Dot Source 变成不受信任的脚本并公开其所有内部函数。 同样,将阻止不受信任的脚本经由 Dot Source 变成受信任的脚本,以防其污染受信任的范围。
  3. 建议避免使用 Start-Job 命令运行脚本块,除非该脚本块已可在“有限语言”模式下成功运行。

建议在对强制执行了 WDAC 的基础结构的管理提供支持但失败时进行的错误处理

如果不打算支持在强制执行了 WDAC 的计算机上运行扩展,建议添加 UI,用于说明强制执行了 WDAC 的基础结构的管理是扩展中不支持的方案,以避免用户混淆。 建议使用类似于现有 Azure 混合服务页面的布局,该页面含有扩展图标和以扩展 iFrame 为中心的文本。

建议在此页面上使用以下文本:

“此扩展当前不支持在强制执行了 Windows Defender 应用程序控制 (WDAC) 的计算机上运行。”

此文本只是一个建议。 如果不确定要使用什么文本,可向 Windows Admin Center 团队发送电子邮件,地址:wacextensionrequests@microsoft.com。

通过扩展检测 WDAC 强制实施

若要按照上一部分中的指南进行操作,需要确定连接到的节点是否已强制执行了 WDAC。 Windows Admin Center 公开了一个名为 getPsLanguageMode 的方法,被定义为 Windows Admin Center 的 WDAC 操作的一部分,用于确定 WDAC 强制实施。

此方法有两个输出:

  • 状态 - HTTPStatusCode 类型
  • psLanguageMode – PsLanguageMode 类型 (enum)

如果 PowerShell 在有限语言模式下运行(psLanguageMode 值为 3 时),可以考虑强制实施 WDAC。

以下 TypeScript 示例代码提供了如何使用此方法的示例:

import { Component, OnInit } from '@angular/core';
import { AppContextService } from '@microsoft/windows-admin-center-sdk/angular';
import { WdacOperations } from '@microsoft/windows-admin-center-sdk/core';
import { PSLanguageMode, PsLanguageModeResult } from '@microsoft/windows-admin-center-sdk/core/data/wdac-operations';

@Component({
  selector: 'default-component',
  templateUrl: './default.component.html',
  styleUrls: ['./default.component.css']
})
export class DefaultComponent implements OnInit {
wdacEnforced: boolean;

  constructor(private appContextService: AppContextService) {
    //
  }

  public ngOnInit(): void {

  }

  public checkWDACEnforced(): void {
    const wdacOperations = new WdacOperations(this.appContextService);
    wdacOperations.getPsLanguageMode(this.appContextService.activeConnection.nodeName).subscribe(
      (response: PsLanguageModeResult) => {
          if (response.psLanguageMode.toString() === PSLanguageMode[PSLanguageMode.ConstrainedLanguage]) {
            this.wdacEnforced = true;
          }
          else {
            this.wdacEnforced = false;
          }
      }
    );
  }
}

在强制执行了 WDAC 的基础结构上测试扩展

阅读有关针对 Windows Admin Center 的 Windows Defender 应用程序控制策略要求的详细信息,以便在强制执行了 WDAC 的基础结构上测试扩展。