WPF 安全策略 - 平台安全性

Windows Presentation Foundation (WPF) 不仅提供各种安全服务,还利用基础平台(例如,操作系统、CLR 和 Internet Explorer)的安全功能。 这些层组合在一起,旨在为 WPF 提供强大且深层防御的安全模型,尝试避免任何单一故障点,如下图所示:

Diagram that shows the WPF security model.

本主题的其余部分主要讨论与 WPF 相关的各个层。

操作系统安全

Windows 的核心提供了几个安全功能,这些功能构成所有 Windows 应用程序(包括使用 WPF 生成的应用程序)的安全基础。 本主题详细介绍了对 WPF 至关重要的这些安全功能的广度,以及 WPF 如何与这些功能集成以提供进一步的深层防御。

Microsoft Windows XP Service Pack 2 (SP2)

除了一般性回顾和强化 Windows 以外,本主题还将介绍 Windows XP SP2 的三个主要功能:

  • /GS 编译

  • Microsoft Windows 更新。

/GS 编译

Windows XP SP2 通过对众多核心系统库进行重新编译提供保护,这些核心系统库包括所有 WPF 依赖项(如 CLR)以帮助缓解缓冲区溢出。 通过使用/GS 形参和 C/C++ 命令行编译器可实现这一点。 虽然应显式避免缓冲区溢出,但 /GS 编译针对由它们无意或恶意创建的潜在漏洞提供了深层防御示例。

以前,缓冲区溢出已导致出现了许多影响较大的安全漏洞。 当攻击者利用代码漏洞时就会发生缓冲区溢出,代码漏洞可让注入的恶意代码通过缓冲区边界写入。 从而让攻击者可以通过重写导致执行攻击者代码的函数返回地址执行代码进程。 结果,恶意代码可以执行具有截获进程相同特权的任意代码。

在较高级别,-GS 编译器标志通过注入特殊安全 cookie 保护部分潜在缓冲区溢出,从而保护具有本地字符串缓冲区的函数返回地址。 函数返回后,安全 cookie 将与其上一个值进行比较。 如果值已更改,可能已发生缓冲区溢出,并且该进程已停止并显示错误条件。 停止的进程将阻止执行潜在的恶意代码。 请参阅 -GS(缓冲区安全性检查)了解详细信息。

WPF 已使用 /GS 标志进行编译,旨在对 WPF 应用程序增加另一层防御。

Windows Vista

Windows Vista 上的 WPF 用户将从操作系统其他的安全增强功能中受益,这些功能包括“最低特权用户访问”、代码完整性检查以及特权隔离。

用户帐户控制 (UAC)

当前,Windows 用户打算使用管理员特权运行,因为许多应用程序都需要此特权才能进行安装和/或执行操作。 其中一个示例就是,可以将默认应用程序设置写入到注册表。

使用管理员特权运行实际上就是指应用程序从授予管理员特权的进程执行。 此方法的安全影响在于,可截获使用管理员特权运行的进程的任何恶意代码都将自动继承这些特权,包括对关键系统资源的访问权限。

保护计算机免受此安全威胁的一种方法就是使用所需的最少特权数运行应用程序。 这就是通常所说的最低特权原则,也是 Windows 操作系统的核心功能。 此功能称为用户帐户控制 (UAC),并通过两种主要方式由 Windows UAC 使用:

  • 若要在默认情况下使用 UAC 特权运行大多数应用程序,即使用户是管理员,也只有需要使用管理员特权的应用程序才会使用管理员特权运行。 要使用管理特权运行,必须以应用程序清单形式或作为安全策略中的一个条目显式标记应用程序。

  • 提供兼容性解决方案(如虚拟化)。 例如,许多应用程序尝试写入受限位置,例如 C:\Program Files。 对于在 UAC 中执行的应用程序,存在基于用户的可选位置无需管理员特权就能写入。 对于在 UAC 中运行的应用程序,UAC 可虚拟化 C:\Program Files,这样认为其写入到其中的应用程序实际上是写入到基于用户的可选位置。 这种兼容性工作可使操作系统来运行许多以前无法在 UAC 中运行的应用程序。

代码完整性检查

Windows Vista 包含更深入的代码完整性检查,有助于防止恶意代码在负载/运行时注入到系统文件或内核。 这超出了系统文件保护。

浏览器承载的应用程序的受限权限进程

浏览器托管的 WPF 应用程序在 Internet 区域沙盒内执行。 WPF 与 Microsoft Internet Explorer 的集成通过其他支持扩展了此保护。

警告

XBAP 需要旧版浏览器(例如 Internet Explorer 和 Firefox)才能运行。 Windows 10 和 Windows 11 通常不支持这些较旧的浏览器版本。 由于安全风险,新式浏览器不再支持 XBAP 应用所需的技术。 不再支持启用 XBAP 的插件。

由于 XAML 浏览器应用程序 (XBAP) 通常由 Internet 区域权限集沙盒化,因此从兼容性的角度来看,移除这些权限不会损害 XAML 浏览器应用程序 (XBAP)。 反而会创建一个附加的深层防御层;如果经过沙箱处理的应用程序能够利用其他层截获此进程,该进程将仍然只有有限特权。

请参阅使用最低特权用户帐户

公共语言运行时的安全性

公共语言运行时 (CLR) 提供了多个主要安全优势,包括确认和验证、代码访问安全性 (CAS) 和安全关键方法。

确认和验证

为了提供程序集隔离和完整性,CLR 将使用验证过程。 CLR 验证可确保程序集通过以下方式进行隔离:即通过验证其指向程序集外部地址的可移植可执行 (PE) 文件的格式。 CLR 验证还可以验证内嵌在程序集中的元数据的完整性。

为了确保类型安全,防止常见安全问题(例如缓冲区溢出)和通过子进程隔离启用沙盒机制,CLR 安全使用了验证概念。

托管应用程序被编译为 Microsoft 中间语言 (MSIL)。 当执行托管应用程序中的方法时,将采用实时 (JIT) 编译方式把 MSIL 编译为本机代码。 JIT 编译包括的验证过程将应用许多众多安全和可靠规则,从而确保代码不会:

  • 违反类型合约

  • 引入缓冲区溢出

  • 随意访问内存。

不允许不符合验证规则的托管代码执行,除非它被视为受信任代码。

可验证代码的优点是 WPF 基于 .NET Framework 生成的主要原因。 从使用验证代码而言,利用潜在漏洞的可能性明显降低。

代码访问安全性

客户端计算机公开了托管应用程序可以访问的各种资源,包括文件系统、注册表、打印服务、用户界面、反射和环境变量。 托管应用程序必须获得 .NET Framework 权限才能访问客户端计算机上的这些资源。 CAS 中的权限是 CodeAccessPermission 的一个子类;CAS 可实现托管应用程序可以访问的各个资源的其中一个子类。

CAS 开始执行时授予托管应用程序的权限集称为一个权限集,由应用程序提供的证据确定。 对于 WPF 应用程序,提供的证据为从中启动应用程序的位置或区域。 CAS 可以标识以下区域:

  • 我的电脑。 从客户端计算机(完全受信任)上启动的应用程序。

  • 本地 Intranet。 从 Intranet 启动的应用程序。 (某种程度上受信任)。

  • Internet。 从 Intranet 启动的应用程序。 (最不受信任)。

  • 受信任的站点。 由受信任用户标识的应用程序。 (最不受信任)。

  • 不受信任的站点。 由不受信任的用户标识的应用程序。 (不受信任)。

对于这些区域中的每一个区域,CAS 都会提供一个预定义的权限集,包括可匹配与之关联的信任级别的权限。 这些设置包括:

  • FullTrust。 适用于从“我的电脑”区域启动的应用程序。 将授予全部可能的权限。

  • LocalIntranet。 适用于从“本地 Intranet”区域启动的应用程序。 将授予权限的子集,以提供对客户端计算机资源适度的访问权限,包括隔离存储、用户界面的无限制访问、无限制使用文件对话框、有限的反射和有限访问环境变量。 不提供对关键资源(如注册表)的权限。

  • Internet。 适用于从“Internet”或“受信任的站点”区域启动的应用程序。 将授予权限的子集,以提供对客户端计算机资源有限的访问权限,包括隔离存储、仅限打开文件和有限的用户界面。 从根本上来说,此权限集将隔离客户端计算机中的应用程序。

CAS 根本不会对标识为来自“不受信任的站点”区域的应用程序授予任何权限。 因此,对它们而言,就不存在预定义的权限集。

下图说明了区域、权限集、权限和资源之间的关系:

Diagram that shows CAS permission sets.

Internet 区域安全沙盒的限制条件同样适用于 XBAP 从系统库导入的任何代码,包括 WPF。 这可确保代码的每一位都是锁定的,即便 WPF 也是如此。 遗憾的是,为了能够执行,XBAP 需要执行要求更多权限的功能,所需的权限比通过 Internet 区域安全沙盒启用的那些功能的权限还要多。

警告

XBAP 需要旧版浏览器(例如 Internet Explorer 和 Firefox)才能运行。 Windows 10 和 Windows 11 通常不支持这些较旧的浏览器版本。 由于安全风险,新式浏览器不再支持 XBAP 应用所需的技术。 不再支持启用 XBAP 的插件。

假设 XBAP 应用程序包括以下页面:

FileIOPermission fp = new FileIOPermission(PermissionState.Unrestricted);
fp.Assert();

// Perform operation that uses the assert

// Revert the assert when operation is completed
CodeAccessPermission.RevertAssert();
Dim fp As New FileIOPermission(PermissionState.Unrestricted)
fp.Assert()

' Perform operation that uses the assert

' Revert the assert when operation is completed
CodeAccessPermission.RevertAssert()

要执行此 XBAP,WPF 基础代码必须执行更多可用功能,而不止是调用 XBAP,包括:

  • 创建用于呈现的窗口句柄 (HWND)

  • 调度消息

  • 加载 Tahoma 字体

从安全角度而言,允许从沙盒应用程序直接访问上述任何操作将会导致灾难性后果。

幸运的是,WPF 可解决这种情况,它通过代表沙盒应用程序使用提升的特权来执行这些操作。 虽然会根据 XBAP 的应用程序域中的有限 Internet 区域安全权限检查所有 WPF 操作,但 WPF(就像其他系统库一样)将获得包括所有可能权限的权限集。

这就要求 WPF 接收提升的特权,同时防止这些特权由宿主应用程序域的 Internet 区域权限集管理。

WPF 通过使用权限的 Assert 方法可实现这一点。 以下代码演示了这种方法。

FileIOPermission fp = new FileIOPermission(PermissionState.Unrestricted);
fp.Assert();

// Perform operation that uses the assert

// Revert the assert when operation is completed
CodeAccessPermission.RevertAssert();
Dim fp As New FileIOPermission(PermissionState.Unrestricted)
fp.Assert()

' Perform operation that uses the assert

' Revert the assert when operation is completed
CodeAccessPermission.RevertAssert()

Assert 实质上是防止 WPF 所需的不受限权限被 XBAP 的 Internet 区域权限所限制。

从平台的角度来看,WPF 负责确保正确使用 Assert;错误地使用 Assert 可能启用恶意代码提升特权。 因此,仅在需要时调用 Assert 至关重要,这样可确保沙盒限制保持不变。 例如,禁止沙盒代码打开任意文件,但允许其使用字体。 WPF 允许沙盒应用程序通过调用 Assert 使用字体功能,以及允许 WPF 代表沙盒应用程序读取已知包含这些字体的文件。

ClickOnce 部署

ClickOnce 是 .NET Framework 附带的一项综合部署技术,并与 Visual Studio 集成在一起(请参阅 ClickOnce 安全性和部署了解详细信息)。 独立的 WPF 应用程序可以使用 ClickOnce 进行部署,但浏览器承载的应用程序必须使用 ClickOnce 进行部署。

使用 ClickOnce 部署的应用程序具有高于代码访问安全性 (CAS) 的额外安全层;实质上,ClickOnce 部署的应用程序会请求所需的权限。 如果它们不超过在其中部署应用程序的区域的权限集,几乎仅授予它们这些权限。 通过将权限集减少至仅限于所需的权限集,即使它们小于通过启动区域权限集提供的那些权限集,应用程序可以访问的资源数也会减少至最低限度。 因此,如果截获到应用程序,将可以降低对客户端计算机的潜在损坏几率。

安全-关键方法

WPF 代码可以使用权限启动 XBAP 应用程序的 Internet 区域沙盒,因此,必须将该代码保留到安全程度最高的审计和控制中。 为实现此要求,.NET Framework 为可提升特权的托管代码提供了新支持。 具体而言,你可以借助 CLR 识别可提升特权的代码并将其标记为 SecurityCriticalAttribute;使用此技术,未标有 SecurityCriticalAttribute 的任何代码都将变得透明。 反之,禁止未标有 SecurityCriticalAttribute 的托管代码提升特权。

警告

XBAP 需要旧版浏览器(例如 Internet Explorer 和 Firefox)才能运行。 Windows 10 和 Windows 11 通常不支持这些较旧的浏览器版本。 由于安全风险,新式浏览器不再支持 XBAP 应用所需的技术。 不再支持启用 XBAP 的插件。

安全关键方法允许将可提升特权的 WPF 代码整理成安全关键内核,使剩余部分透明。 隔离安全关键代码可使 WPF 工程团队关注高于标准安全实践的安全关键内核上的其他安全分析和源控件(请参阅 WPF 安全策略 - 安全工程)。

请注意,.NET Framework 允许受信任的代码通过以下方式扩展 XBAP Internet 区域沙盒:即允许开发人员编写标记为 AllowPartiallyTrustedCallersAttribute (APTCA) 并部署到用户的全局程序集缓存 (GAC) 的托管程序集。 将程序集标记为 APTCA 是高度敏感的安全操作,因为它允许任何代码调用该程序集,包括来自 Internet 的恶意代码。 执行此操作时,要特别注意并且必须采用最佳做法,用户必须选择信任该软件才能完成安装。

Microsoft Internet Explorer 安全

除减少安全问题和简化安全配置外,Microsoft Internet Explorer 6 (SP2) 还包含好几个增强安全的功能,从而提高了 XAML 浏览器应用程序 (XBAP) 用户的安全。 这些功能的主旨是尝试允许用户更好地控制它们的浏览体验。

警告

XBAP 需要旧版浏览器(例如 Internet Explorer 和 Firefox)才能运行。 Windows 10 和 Windows 11 通常不支持这些较旧的浏览器版本。 由于安全风险,新式浏览器不再支持 XBAP 应用所需的技术。 不再支持启用 XBAP 的插件。

在 IE6 SP2 之前,用户可能会受限于以下任一项:

  • 随机弹出窗口。

  • 混淆的脚本重定向。

  • 某些网站上出现大量安全对话框。

在某些情况下,不受信任的网站将尝试通过诱导安装用户界面 (UI) 或反复显示 Microsoft ActiveX 安装对话框(即使用户可能已取消)攻击用户。 使用这些技术,有可能会有相当多的用户上当受骗,从而导致安装间谍软件应用程序。

IE6 SP2 包括用于缓解围绕用户启动这些问题类型的多个功能。 用户在执行操作(称为用户启动)前单击了某个链接或页面元素时,IE6 SP2 就会检测到该操作并以不同于页面上脚本触发的类似操作的方式对待。 例如,IE6 SP2 含有一个弹出窗口阻止程序,用于检测页面创建弹出窗口之前用户单击某个按钮的时间。 此程序可使 IE6 SP2 允许大多数没有威胁的弹出窗口,同时阻止用户既没有要求也不需要的弹出窗口。 阻止的弹出窗口被捕获后放在新的“信息栏”下,以便用户手动重写块和查看弹出窗口。

相同的用户启动逻辑也适用于“打开/保存”安全提示。 ActiveX 安装对话框始终显示在“信息栏”中,除非它们表示从以前安装的控件进行升级。 这些度量值组合在一起,可提供用户更安全、更可控的用户体验,因为诱导他们安装不需要的软件或恶意软件的站点受到了保护。

这些功能还可以对使用 IE6 SP2 浏览网站(允许他们下载和安装 WPF 应用程序)的用户提供保护。 特别是,这是因为 IE6 SP2 提供的用户体验更好,降低了安装恶意或“狡猾”的应用程序的几率,而不考虑用于构建它的技术类型,包括 WPF。 WPF 通过使用 ClickOnce 进一步增强这些保护,以便通过 Internet 下载其应用程序。 由于 XAML 浏览器应用程序是在 Internet 区域安全沙盒内执行,因此可以无缝地启动它们。 另一方面,独立的 WPF 应用程序需要完全信任才能执行。 对于这些应用程序,ClickOnce 将在启动过程示安全对话框,以通知使用应用程序的其他安全要求。 但是,必须由用户启动,必须由用户启动的逻辑进行管理并且可以取消。

Internet Explorer 7 包含并扩展了作为持续提供安全承诺一部分的 IE6 SP2 的安全功能。

另请参阅