请求程序的安全注意事项

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

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

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

管理请求程序的安全问题的最简单机制包括正确选择运行所用的用户帐户。

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

默认情况下,当请求程序充当 COM 客户端时,如果未以这些帐户身份运行,则会用 E_ACCESSDENIED 自动拒绝任何 COM 调用,甚至不会去实现 COM 方法。

禁用 COM 异常处理

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

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

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

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

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

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

  • 允许所有进程访问以调入请求程序进程。

    此选项可能适合绝大多数请求程序,并由其他 COM 服务器使用,例如,所有基于 SVCHOST 的 Windows 服务都已在使用此选项,默认情况下所有 COM+ 服务也是如此。

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

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

    若要允许所有进程 COM 访问请求程序,可以将 NULL 安全描述符作为 CoInitializeSecurity 的第一个参数进行传递。 (请注意,对于整个过程,必须最多调用一次 CoInitializeSecurity。)

    以下代码示例演示请求程序如何在 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。 有关掩蔽安全性的详细信息,请参阅掩蔽

    以下代码示例演示请求程序应该如何在 Windows 7 和 Windows Server 2008 R2 及更早版本中(或在 Windows 8 和 Windows Server 2012 及更高版本中,但前提是不需要 RVSS 兼容性)调用 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 调用。
  • 仅允许指定进程访问以调入请求程序进程。

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

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

    • Local System

    • Local Service

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

    • Network Service

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

    • 本地管理员组的成员

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

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

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

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

例如,指定的请求程序进程通常不需要以管理员或备份操作员帐户身份运行。 出于安全原因,最好不要人为提升进程特权来支持 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 函数。