Windows PowerShell拦截恶意代码

Don Jones

是否记得在 Windows Vista 尚处于测试阶段时,对于很早版本的新命令行 shell(代号为“Monad”)存在着许多争论?(它的最终名称是 Windows PowerShell。)当时,许多主流媒体报导了“首个 Windows Vista 病毒。”实际上,

这个“病毒”只是一个以“Monad”为目标的概念证明恶意软件脚本。为运行脚本,必须专门配置“Monad”本身 — 脚本在默认设置情况下无法运行。并且,在这些报导出现时,Microsoft 已宣布不会将“Monad”作为 Windows Vista® 的一部分发布。简而言之,整个情形是无事生非(或者至少是非常夸大其辞)。

随着 Windows PowerShellTM 的日渐普及(它的下载次数已超过一百万次),有人使用它来创建恶意脚本的几率也增加了。在 Windows PowerShell 中编写潜在破坏性脚本的能力是前提;任何管理工具(包括 Windows PowerShell、cmd.exe 和 VBScript)都可被恶意使用。因此,不能假定给定的 PS1 文件没有危害。

幸运的是,Windows PowerShell 已默认配置为不运行任何脚本,因此,恶意脚本必须在您的帮助下才会运行。本月,我要预测它可能发生的方式。这并不会影响 Windows PowerShell 的形象 — 我认为 Microsoft 在设计能避免各种风险的脚本 shell 方面已做得非常不错。但是,还是应对其进行讨论,以帮助您做好拦截该潜在攻击的准备。

默认安全

值得注意的是,Windows PowerShell 是实施著名的高信度计算计划后由 Microsoft 设计的首款语言。安全专家 Michael Howard(Writing Secure Code 一书的作者)是 Windows PowerShell 团队的“安全使者”。他帮助确保代码编写得尽可能安全,最为重要的,确保 shell 的出厂配置尽可能安全。

首先,让我们快速查看一下初始 Windows PowerShell 安全设置。默认情况下,shell 不会在您双击具有 PS1 文件扩展名的文件时运行这些文件。该扩展名针对的是记事本。实际上,在默认情况下,由于名为执行策略的内置功能描述了运行脚本的条件,shell 根本不会运行脚本。它出厂设置为 Restricted,从而禁止运行所有脚本并仅在交互使用时启用 shell。可使用 Set-ExecutionPolicy cmdlet 或通过 Microsoft 提供的组策略管理模块(ADM 文件)更改执行策略。(可在以下地址获取 ADM 文件:go.microsoft.com/fwlink/?LinkId=102940。)图 1 显示了可设置的执行策略。

图 1 选择安全执行策略

图 1** 选择安全执行策略 **(单击该图像获得较大视图)

执行策略具有少量例外情况。具体来说,即使在设置为 Restricted 时,它也会允许 shell 导入 Microsoft 提供且随 shell 安装的少数特殊 XML 配置文件。这些文件用于提供特定功能,如扩展为 Microsoft® .NET Framework 类型和大部分 .NET 对象类型的默认格式布局。因此,它们绝对是您希望 shell 在启动时加载的文件。

尽管这些文件可能且确实包含可执行代码,但它们已经由 Microsoft 进行数字签名。任何方式的篡改都将致使签名无效,并且在发生该情况后,shell 将不会在启动时导入文件。此设计使文件非常安全,不受可能试图将恶意代码插入其中的恶意软件的侵害。

当然,即使保留在 Restricted 状态,执行策略也可防止在启动时执行自身的 Windows PowerShell 配置文件脚本。Windows PowerShell 不会默认创建配置文件脚本,但是它会在四个特定位置搜索特定文件名称,如果找到这些名称,就会尝试每次在 shell 启动时执行这些脚本。(随 Windows PowerShell 安装的文档提供了有关用于配置文件脚本的文件夹和文件名称的详细信息。)配置文件是我要讨论的关键利用点。

修改执行策略

本月 Cmdlet

与 Set-AuthenticodeSignature 搭配的是 Get-AuthenticodeSignature。该 cmdlet 旨在检查数字签名脚本并向您提供签名的详细信息。只需将它指向存在问题的文件,您将不仅可看到文件是否已签署,还可看到签名是否完整、使用何种证书来签署文件等等。除可用于 Windows PowerShell 脚本外,该 cmdlet 还可用于已签名的可执行程序,如:

PS C:\Program Files\Microsoft Office\Office12>
Get-AuthenticodeSignature excel.exe | Format-List *

通过运行该命令,可看到可执行程序已由 Microsoft Corp. 使用 Microsoft 代码签名 CA 颁发的证书进行签名。

命令结果

命令结果  (单击该图像获得较大视图)

强调一下,在默认情况下,很难 — 如果并非不可能 — 让 Windows PowerShell 执行任何代码,更别提恶意代码。仅当修改了执行策略后,恶意脚本才可能变为可能执行。清楚点讲,本专栏并非有关 Windows PowerShell 安全漏洞的警钟;相反,它旨在共享可强化您系统的一些最佳实践。

最低级执行策略为 Unrestricted,它允许运行所有脚本,而不进行限制或质疑 — 就像多年来使用 VBScript 和批处理文件出现的情况一样,这是不尽人意的。如果将 shell 设置为 Unrestricted,只会招致恶意脚本的出现并导致损坏。如果选择了 Unrestricted 设置,且出现脚本并攻击了您,请确保您能解释清楚选择 Unrestricted 设置的原因,并做好在解释病毒如何破坏您的环境时坦白您决策的准备!

公平地讲,即使设置为 Unrestricted,Windows PowerShell 仍会尝试检测从 Internet 下载的脚本并在运行前向您提出警告。但是,关键在于将执行策略设置为 Unrestricted 不是个好主意。

签名脚本

允许执行脚本的最安全执行策略是 AllSigned。顾名思义,此设置仅执行具有使用受信任证书创建的完整数字签名的脚本(不象任何旧签名)。签名脚本需要您获取 III 类数字证书 — 更具体点讲,Microsoft Authenticode 代码签名的证书。此类证书可从公司的内部公钥基础结构 (PKI)(如果有)获取或从商业证书颁发机构 (CA)(如 CyberTrust、Thawte 和 VeriSign)处购买。

如果要了解您的计算机上是否安装了任何可用于签名脚本的证书,请使用以下 cmdlet:

Get-ChildItem CERT: -recurse –codeSigningCert

在 Windows® 计算机上安装证书后,使用 Set-AuthenticodeSignature cmdlet 来创建并应用数字签名,它会在脚本结尾处显示为一系列乱码形式的注释行。某些脚本编辑器可提供选项来将签名应用到脚本文件(包括在保存脚本时自动对其进行签名),这样将非常便利。

AllSigned 是用于生产环境的最佳执行策略。尽管它无法完全杜绝恶意脚本,但是它却可确保恶意脚本已经过签名,因此可跟踪脚本的作者(假定您的 Windows 计算机已配置为仅信任可靠 CA,但这不在本专栏的讨论范围内)。有趣的是,Windows Script Host (WSH) 5.6 和更高版本可用类似的 TrustPolicy 设置(也需要数字签名)配置,但是,我很少遇到管理员实际使用此设置。

以下为迄今为止的快速回顾。通过将执行策略设置为 Restricted,您将不再需要担心恶意脚本,但是您也无法运行有益的脚本。通过将执行策略配置为 AllSigned,shell 允许经过签名的脚本,它非常安全,因为极少恶意脚本作者希望将经确认且可追踪的身份应用到其作品中。相反,Unrestricted 设置极不安全,如果使用它,可能最终会受到某些恶意脚本的攻击。(请注意,我并不认为 Unrestricted 设置是一种特殊漏洞,因为它并不假装为任何事物,仅是不安全。如果要使用此设置,您大概也知道会得到什么结果。)

从侧门偷袭

还有一个执行策略设置:RemoteSigned。我想这个设置是大部分管理员正在使用的设置,其原因仅是感觉它比 Unrestricted 更安全且没有 AllSigned 麻烦。RemoteSigned 不需要本地脚本的签名。驻留在本地驱动器上的 PS1 文件无需签名即可运行。除非经过签名,否则不会运行远程脚本 — 主要是通过 Internet Explorer® 或 Outlook®(这些应用程序使用特殊的标志来标记下载的文件)从 Internet 下载的脚本。

但是,RemoteSigned 设置可能给您一种安全的错觉。首先,很容易下载到没有应用特殊标志的远程脚本。例如,非 Microsoft 浏览器以及大部分非 Microsoft 电子邮件客户端通常不会设置此标志。必须注意:缺少该标志,Windows PowerShell 会将下载的脚本视为本地脚本,即表示不需要签名。同样,我也不认为它是一个重大漏洞。必须实际下载脚本,打开 Windows PowerShell,然后手动执行脚本才能运行它。很难欺骗某人执行所有这些步骤,并且管理员通常是网络中唯一安装 Windows PowerShell 的人员,应更加清楚这点。

然而,RemoteSigned 确实提供了一个恶意软件可偷袭的重大“侧门”。还记得那些 Windows PowerShell 配置文件脚本吗?只要它们存在(无论是您还是某个恶意软件创建的),每运行一次 Windows PowerShell,它们就会执行一次。并且,在使用 RemoteSigned 执行策略时,您的配置文件脚本(它为本地脚本)无需签名。

它的具体情形是这样的:

  1. 某些恶意软件进入您的系统,然后创建一个 shell 配置文件脚本或将恶意代码插入现有配置文件脚本中。恶意软件通常以登录的用户帐户名义运行,而该帐户一般都具有修改配置文件脚本的权限。
  2. 在打开 Windows PowerShell 时,您并未意识到配置文件脚本已被创建或修改为包含恶意代码。然而代码开始执行并造成损害。如果您习惯以管理员凭据打开 Windows PowerShell,则损害将更加严重。这种情形却非常普遍,因为在使用 shell 时,需要使用管理员权限来执行要用 shell 实现的所有任务。

然后,配置文件允许任意的恶意代码在您不知情的情况下执行,且 RemoteSigned 执行策略也允许此种情形发生。

保护配置文件

保护配置文件的唯一好方法是:使用 AllSigned 执行策略。使用 AllSigned 时,您的配置文件脚本也必须经过数字签名;否则,Windows PowerShell 在启动时不会执行它们。并且,如果您已签名配置文件脚本,对它们的恶意修改会破坏其数字签名,使它们无法运行 — 实际上,在启动时,Windows PowerShell 会提示出现问题。AllSigned 实际是用于需允许执行脚本的生产环境的唯一安全执行策略设置。

也有其他方法,但更加复杂且可靠度更差。可针对 Windows PowerShell 查找的四个文件创建空白配置文件脚本文件。使用新用户帐户(我将称它为“Profile Editor”)来创建这些文件并设置文件的 NTFS 权限,这样,只有 Profile Editor 帐户才能修改它们。其他帐户仅拥有只读访问权限。

现在,除非要编辑配置文件,否则切勿使用 Profile Editor 帐户来登录计算机。通过这种方法,您的普通用户帐户将无法修改配置文件脚本。并且,在您使用普通帐户登录时运行的任何恶意脚本也无法修改脚本。如果恶意软件恰好在您以 Profile Editor 帐户登录时运行,会发生什么情况?当然,总有需要您以 Profile Editor 帐户登录来编辑配置文件脚本的时候,您应注意到发生的变化。

也可启动自己的安全系统,方法是创建使用由严格文件权限控制的所有用户配置文件脚本(如刚才所述)。在该脚本中,编写代码,让代码使用 Get-AuthenticodeSignature cmdlet 检查 shell 查找的其他配置文件上的数字签名。这实质上是让您要求配置文件脚本有签名,而无需其他脚本有签名。

然而,AllSigned 执行策略是一种用于保护配置文件的更加彻底的方法。我的建议是连接到网络的所有计算机均使用 Restricted 执行策略(最好采用组策略)。它将覆盖任何本地设置,并确保新的域计算机自动设置为不允许有脚本。必须允许有脚本的计算机应具有设置 AllSigned 执行策略的备用组策略。必须对所有脚本执行数字签名,但是由于知道只有来自可识别作者的受信任脚本才能在您的环境中执行,因此大可高枕无忧。

Don Jones 是 SAPIEN Technologies 的首席脚本权威和《Windows PowerShell: TFM (SAPIEN Press, 2007) 的合著者。可通过 www.ScriptingAnswers.com 与他联系。

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.