请求者的安全注意事项

VSS 基础结构要求 VSS 请求者(例如备份应用程序)能够同时充当 COM 客户端和服务器。

充当服务器时,请求者会公开一组 COM 回调接口,这些接口可从外部进程 (调用,例如编写器或 VSS 服务) 。 因此,请求者需要安全地管理哪些 COM 客户端能够对其进程进行传入 COM 调用。

同样,请求者可以充当 VSS 编写器或 VSS 服务提供的 COM API 的 COM 客户端。 特定于请求者的安全设置必须允许从请求者向这些其他进程发出 COM 调用。

管理请求者安全问题的最简单机制涉及正确选择运行请求者的用户帐户。

请求者通常需要在管理员组或备份操作员组成员的用户下运行,或者以本地系统帐户的身份运行。

默认情况下,当请求者充当 COM 客户端时,如果它未在这些帐户下运行,则任何 COM 调用都将自动被拒绝并 E_ACCESSDENIED,甚至无需访问 COM 方法实现。

禁用 COM 异常处理

开发请求程序时,设置 COM COMGLB_EXCEPTION_DONOT_HANDLE全局选项标志以禁用 COM 异常处理。 执行此操作非常重要,因为 COM 异常处理可以屏蔽 VSS 应用程序中的严重错误。 屏蔽的错误会使进程处于不稳定和不可预知的状态,从而导致损坏和挂起。 有关此标志的详细信息,请参阅 IGlobalOptions

设置请求者默认 COM 访问检查权限

请求者需要注意,当其进程充当服务器 (例如,允许编写者修改备份组件文档) 时,他们必须允许来自其他 VSS 参与者(如编写器或 VSS 服务)的传入调用。

但是,默认情况下,Windows 进程将仅允许在同一登录会话下运行的 COM 客户端 (SELF SID) 或在本地系统帐户下运行。 这是一个潜在的问题,因为这些默认值不足以用于 VSS 基础结构。 例如,编写器可能作为“备份操作员”用户帐户运行,该帐户既不是在与请求方进程相同的登录会话中,也不是本地系统帐户。

为了处理此类问题,每个 COM 服务器进程都可以进一步控制是否允许 RPC 或 COM 客户端执行由服务器 (请求者实现的 COM 方法,在这种情况下,通过使用 CoInitializeSecurity 设置进程范围的“默认 COM 访问检查权限”来) 。

请求者可以显式执行以下操作:

  • 允许所有进程访问以调用请求方进程。

    此选项可能足以满足绝大多数请求者的需求,并且可供其他 COM 服务器使用,例如,所有基于 SVCHOST 的 Windows 服务都已在使用此选项,默认情况下,所有 COM+ 服务都已使用此选项。

    允许所有进程执行传入 COM 调用不一定是安全漏洞。 与所有其他 COM 服务器一样,充当 COM 服务器的请求者始终保留在其进程中实现的每个 COM 方法上授权其客户端的选项。

    请注意,默认情况下,VSS 实现的内部 COM 回调受到保护。

    若要允许所有进程 COM 访问请求者,可以将 NULL 安全描述符作为 CoInitializeSecurity 的第一个参数传递。 (请注意,对于整个过程,最多只能调用一次 CoInitializeSecurity 。有关 CoInitializeSecurity calls.) 的详细信息,请参阅 COM 文档或 MSDN

    下面的代码示例演示了请求者如何在 Windows 8 和 Windows Server 2012 及更高版本中调用 CoInitializeSecurity,以便与远程文件共享的 VSS 兼容 (RVSS) :

    // Initialize COM security.
       hr = CoInitializeSecurity(
            NULL,                          //  PSECURITY_DESCRIPTOR         pSecDesc,
            -1,                            //  LONG                         cAuthSvc,
            NULL,                          //  SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
            NULL,                          //  void                        *pReserved1,
            RPC_C_AUTHN_LEVEL_PKT_PRIVACY, //  DWORD                        dwAuthnLevel,
            RPC_C_IMP_LEVEL_IMPERSONATE,   //  DWORD                        dwImpLevel,
            NULL,                          //  void                        *pAuthList,
            EOAC_STATIC,                   //  DWORD                        dwCapabilities,
            NULL                           //  void                        *pReserved3
            );
    

    使用 CoInitializeSecurity 显式设置请求者的 COM 级别安全性时,应执行以下操作:

    • 将身份验证级别至少设置为 RPC_C_AUTHN_LEVEL_PKT_INTEGRITY。 为了提高安全性,请考虑使用 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    • 将模拟级别设置为 RPC_C_IMP_LEVEL_IMPERSONATE
    • 将遮盖安全功能设置为 EOAC_STATIC。 有关隐藏安全性的详细信息,请参阅 隐藏

    下面的代码示例演示了如果) 不需要 RVSS 兼容性,则请求者如何在 Windows 7 和 Windows Server 2008 R2 及更早版本中调用 CoInitializeSecurity (,或者在 Windows 8 和 Windows Server 2012 及更高版本中调用 CoInitializeSecurity

    // Initialize COM security.
       hr = CoInitializeSecurity(
            NULL,                          //  PSECURITY_DESCRIPTOR         pSecDesc,
            -1,                            //  LONG                         cAuthSvc,
            NULL,                          //  SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
            NULL,                          //  void                        *pReserved1,
            RPC_C_AUTHN_LEVEL_PKT_PRIVACY, //  DWORD                        dwAuthnLevel,
            RPC_C_IMP_LEVEL_IDENTIFY,      //  DWORD                        dwImpLevel,
            NULL,                          //  void                        *pAuthList,
            EOAC_NONE,                     //  DWORD                        dwCapabilities,
            NULL                           //  void                        *pReserved3
            );
    

    使用 CoInitializeSecurity 显式设置请求者的 COM 级别安全性时,应执行以下操作:

    • 将身份验证级别设置为至少 RPC_C_AUTHN_LEVEL_CONNECT。 为了提高安全性,请考虑使用 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    • 将模拟级别设置为 RPC_C_IMP_LEVEL_IDENTIFY 除非请求方进程需要允许模拟与 VSS 无关的特定 RPC 或 COM 调用。
  • 仅允许对指定进程进行访问,以调用请求方进程。

    COM 服务器 (,例如调用 CoInitializeSecurity (使用非 NULL 安全描述符作为第一个参数)的请求者) ,可以使用描述符将自身配置为仅接受来自属于一组特定帐户的用户的传入调用。

    请求者必须确保在有效用户下运行的 COM 客户端有权调用其进程。 在第一个参数中指定安全描述符的请求者必须允许以下用户对请求方进程执行传入调用:

    • Local System

    • Local Service

      Windowsxp: 在 Windows Server 2003 之前不支持此值。

    • Network Service

      Windowsxp: 在 Windows Server 2003 之前不支持此值。

    • 本地管理员组的成员

    • 本地备份操作员组的成员

    • 以下注册表位置中指定的特殊用户,其REG_DWORD值为“1”

显式控制用户帐户对请求者的访问权限

在某些情况下,限制对请求者访问作为本地系统运行的进程,或者在本地管理员或本地备份操作员组下运行的进程可能过于严格。

例如,通常不需要在管理员或备份操作员帐户下运行指定的请求方进程。 出于安全原因,最好不要人为地提升进程权限以支持 VSS。

在这些情况下,必须修改HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VSS VssAccessControl 注册表项,以指示 VSS 指定用户可以安全地运行 VSS 请求程序。\

在此密钥下,必须创建一个与要授予或拒绝访问权限的帐户同名的子项。 此子项必须设置为下表中的值之一。

含义
0 拒绝用户访问编写器和请求者。
1 授予用户对编写器的访问权限。
2 向用户授予对请求者的访问权限。
3 向用户授予对编写者和请求者的访问权限。

 

以下示例授予对“MyDomain\MyUser”帐户的访问权限:

HKEY_LOCAL_MACHINE
   SYSTEM
      CurrentControlSet
         Services
            VSS
               VssAccessControl
                  MyDomain\MyUser = 2<dl>
<dt>

                  Data type
</dt>
<dd>                  REG_DWORD</dd>
</dl>

此机制还可用于显式限制以其他方式允许的用户运行 VSS 请求程序。 以下示例将限制来自“ThatDomain\Administrator”帐户的访问:

HKEY_LOCAL_MACHINE
   SYSTEM
      CurrentControlSet
         Services
            VSS
               VssAccessControl
                  ThatDomain\Administrator = 0<dl>
<dt>

                  Data type
</dt>
<dd>                  REG_DWORD</dd>
</dl>

用户 ThatDomain\Administrator 将无法运行 VSS 请求程序。

执行系统状态的文件备份

如果请求者通过备份单个文件而不是使用卷映像进行备份来执行系统状态备份,则必须调用 FindFirstFileNameWFindNextFileNameW 函数来枚举位于以下目录中的文件上的硬链接:

  • Windows\system32\WDI\perftrack\
  • Windows\WINSXS\

这些目录只能由管理员组的成员访问。 出于此原因,此类请求者必须在系统帐户或作为管理员组成员的用户帐户下运行。

Windows XP 和 Windows Server 2003: 在 Windows Vista 和 Windows Server 2008 之前,不支持 FindFirstFileNameWFindNextFileNameW 函数。