Windows 窗体中额外的安全注意事项

.NET Framework 安全设置可能导致应用程序在部分信任环境中运行的方式与在本地计算机上运行的方式不同。 .NET Framework 限制对关键本地资源的访问,例如文件系统、网络和非托管 API 等。 安全设置会影响对 Microsoft Windows API 或安全系统无法验证的其他 API 进行调用的能力。 安全性还会影响应用程序的其他方面,包括文件和数据访问以及打印。 有关在部分信任环境中访问文件和数据的详细信息,请参阅 Windows 窗体中更加安全的文件和数据访问。 有关在部分信任环境中进行打印的详细信息,请参阅 Windows 窗体中更加安全的打印

以下各部分讨论如何使用剪贴板、如何执行窗口操作以及如何从在部分信任环境下运行的应用程序调用 Windows API。

剪贴板访问

UIPermission 类控制对剪贴板的访问,关联的 UIPermissionClipboard 枚举值指示访问级别。 下表显示可能的权限级别。

UIPermissionClipboard 值 说明
AllClipboard 可以不受限制地使用剪贴板。
OwnClipboard 使用剪贴板时有某些限制。 将数据放置到剪贴板中的能力(“复制”或“剪切”命令操作)是不受限制的。 接受粘贴的固有控件(例如文本框)可接受剪贴板数据,但用户控件无法以编程方式从剪贴板读取数据。
NoClipboard 不能使用剪贴板。

默认情况下,本地 Intranet 区域接收 AllClipboard 访问,Internet 区域接收 OwnClipboard 访问。 这意味着,应用程序可以将数据复制到剪贴板,但无法通过编程方式进行粘贴或从剪贴板进行读取。 这些限制可以防止不完全受信任的程序读取另一应用程序复制到剪贴板的内容。 如果应用程序需要完全的剪贴板访问权限,但你又不具有这些权限,则必须提升应用程序的权限。 有关提升权限的详细信息,请参阅常规安全策略管理

窗口操作

UIPermission 类还控制执行窗口操作和其他 UI 相关操作的权限,关联的 UIPermissionWindow 枚举值指示访问级别。 下表显示可能的权限级别。

默认情况下,本地 Intranet 区域接收 AllWindows 访问,Internet 区域接收 SafeTopLevelWindows 访问。 这意味着,在“Internet”区域中,应用程序可以执行大多数窗口操作和 UI 操作,但窗口的外观将被修改。 修改后的窗口在第一次运行时会显示一条气球状通知,包含修改的标题栏文本,并需要标题栏上有一个关闭按钮。 气球状通知和标题栏会向应用程序的用户指示:应用程序正在部分信任环境下运行。

UIPermissionWindow 值 说明
AllWindows 用户可以不受限制地使用所有窗口和用户输入事件。
SafeTopLevelWindows 用户只能使用较安全的顶级窗口和子窗口进行绘制,并且只能在这些顶级窗口和子窗口中使用用户界面的用户输入事件。 这些较安全窗口具有明显的标签,并具有最小化和最大化限制。 这些限制可以防止潜在的有害欺骗攻击(例如模拟系统登录屏幕或系统桌面),还可以限制对父窗口、与焦点相关的 API 的编程访问以及 ToolTip 控件的使用,
SafeSubWindows 用户只能使用较安全子窗口进行绘制,并且只能在该子窗口中使用用户界面的用户输入事件。 浏览器中显示的控件就是一个较安全子窗口的示例。
NoWindows 用户不能使用任何窗口或用户界面事件。 不能使用任何用户界面。

UIPermissionWindow 枚举标识的每个权限级别仅允许比更高一级的级别更少的操作。 下表指出了受 SafeTopLevelWindowsSafeSubWindows 值限制的操作。 有关每个成员所需的确切权限,请参阅 .NET Framework 类库文档中有关该成员的参考资料。

SafeTopLevelWindows 权限限制下表中列出的操作。

组件 受限制的操作
Application - 设置 SafeTopLevelCaptionFormat 属性。
Control - 获取 Parent 属性。
- 设置 Region 属性。
- 调用 FindFormFocusFromChildHandleFromHandlePreProcessMessageReflectMessageSetTopLevel 方法。
- 如果返回的控件不是调用控件的子级,则调用 GetChildAtPoint 方法。
- 修改容器控件内部的控件焦点。
Cursor - 设置 Clip 属性。
- 调用 Hide 方法。
DataGrid - 调用 ProcessTabKey 方法。
Form - 获取 ActiveFormMdiParent 属性。
- 设置 ControlBoxShowInTaskbarTopMost 属性。
- 将 Opacity 属性设置为低于 50%。
- 以编程方式将 WindowState 属性设置为 Minimized
- 调用 Activate 方法。
- 使用 NoneFixedToolWindowSizableToolWindowFormBorderStyle 枚举值。
NotifyIcon - 完全限制使用 NotifyIcon 组件。

除了 SafeTopLevelWindows 值施加的限制外,SafeSubWindows 值限制下表中列出的操作。

组件 受限制的操作
CommonDialog - 显示从 CommonDialog 类派生的对话框。
Control - 调用 CreateGraphics 方法。
- 设置 Cursor 属性。
Cursor - 设置 Current 属性。
MessageBox - 调用 Show 方法。

承载第三方控件

如果窗体承载第三方控件,可能会发生另一种窗口操作。 第三方控件是指并非由你自己开发和编译的任何自定义 UserControl。 尽管承载方案难以侵入,但第三方控件理论上仍有可能扩展其呈现图面以覆盖整个窗体区域。 此控件随后即可模仿关键对话框,并从你的用户那里请求用户名/密码组合或银行帐号等信息。

若要限制这种潜在风险,应仅使用来自可信任的供应商的第三方控件。 如果所使用的第三方控件是从无法验证的源下载的,则建议检查源代码是否有潜在侵入风险。 确认源无恶意后,应自己编译程序集以确保源与程序集匹配。

Windows API 调用

如果你的应用程序设计需要从 Windows API 调用函数,则表示你正在访问非托管代码。 在这种情况下,当你使用 Windows API 调用或值时,无法确定代码将对窗口或操作系统执行的操作。 SecurityPermission 类和 SecurityPermissionFlag 枚举的 UnmanagedCode 值控制对非托管代码的访问。 应用程序仅在被授予 UnmanagedCode 权限时才可以访问非托管代码。 默认情况下,只有本地运行的应用程序才能调用非托管代码。

某些 Windows 窗体成员提供需要 UnmanagedCode 权限的非托管访问。 下表列出了需要该权限的 System.Windows.Forms 命名空间中的成员。 有关各个成员所需权限的详细信息,请参阅 .NET Framework 类库文档。

组件 成员
Application - AddMessageFilter 方法
- CurrentInputLanguage 属性
- Exit 方法
- ExitThread 方法
- ThreadException 事件
CommonDialog - HookProc 方法
- OwnerWndProc\ 方法
- Reset 方法
- RunDialog 方法
Control - CreateParams 方法
- DefWndProc 方法
- DestroyHandle 方法
- WndProc 方法
Help - ShowHelp 方法
- ShowHelpIndex 方法
NativeWindow - NativeWindow
Screen - FromHandle 方法
SendKeys - Send 方法
- SendWait 方法

如果你的应用程序无权调用非托管代码,则应用程序必须请求 UnmanagedCode 权限,或者你应该考虑实现这些功能的其他方法;在许多情况下,Windows 窗体提供针对 Windows API 函数的托管替代项。 如果不存在任何备选方法并且应用程序必须访问非托管代码,则必须提升应用程序的权限。

调用非托管代码的权限使应用程序几乎可以执行任何操作。 因此,应该只向来自于受信任源的应用程序授予调用非托管代码的权限。 另外,根据应用程序的不同,调用非托管代码的应用程序功能块可以是可选的,或者只在完全受信任的环境中启用。 有关危险权限的详细信息,请参阅危险权限和策略管理。 有关提升权限的详细信息,请参阅常规安全策略管理

另请参阅