ACS 安全准则

更新时间:2015 年 6 月 19 日

适用于:Azure

应用于

  • Microsoft Azure Active Directory 访问控制(也称为访问控制服务或 ACS)

  • Windows Identity Foundation (WIF)

总结

本主题整合 ACS 的安全准则。 从安全的角度看,使用这些准则可提高实现质量。 在复查应用程序的体系结构、复查代码和日志记录安全 Bug 以及复查生产部署时,可以使用这些准则。 这些指南参考了有关如何完成特定任务的规范性步骤和概念主题的详细信息,以了解有关 ACS 的特定功能或功能的详细信息。

目标

  • 解决与 ACS 上下文中应用程序代码和配置相关的安全问题。

  • 解决与 ACS 配置相关的安全问题。

  • 解决与 ACS 上下文中的 Azure 部署相关的安全问题。

以下是与应用程序的代码和配置相关的安全准则。

  • 考虑将重放检测功能 (DetectReplayedTokens) 设置为 true。

  • wsFederationrequireHttps 属性设置为 true。

  • cookieHandlerrequireSsl 属性设置为 true。

  • sessionTokenRequirement 的生存期属性设置主动值。

  • 列出 issuerNameRegistry 中的受信任 STS(令牌颁发者)。

  • 应用程序应该使用 audienceUri 接受的范围令牌。

考虑将重放检测功能 (DetectReplayedTokens) 设置为 true

WIF 具有一个专用于安全令牌服务 (STS) 持有者令牌的重放检测缓存,该缓存只是以前使用的 STS 令牌的缓存。 当客户端第一次使用 STS 令牌向信赖方进行身份验证时,它将收到会话安全令牌,并会使用该令牌向任何其他请求的信赖方进行身份验证。 它将通过安全套接字层 (SSL) 执行此操作,以免会话安全令牌被盗用。 如果客户端或攻击者尝试使用客户端已使用的 STS 令牌向信赖方进行身份验证时,信赖方可以在重放缓存中查找该 STS 令牌并拒绝该请求。

该缓存并不保证令牌从不会重放。 它根据缓存的大小、STS 令牌的到期时间,以及信赖方收到唯一身份验证请求的速率执行尽最大努力的检测。 我们强烈建议你设置缓存大小和 STS 令牌到期时间,以便信赖方能够在性能和安全性之间找到适当平衡。

例如:

<securityTokenHandlers>
  <securityTokenHandlerConfiguration>
    <tokenReplayDetection enabled="true" capacity="1000" expirationPeriod="500"/>
  </securityTokenHandlerConfiguration>
</securityTokenHandlers>

注意

使用此功能将引入服务器相关性,这可能导致在负载平衡环境(包括 Azure)中出现可伸缩性问题。 为了解决此问题,可考虑使用抽象基类 Microsoft.IdentityModel.Tokens.TokenReplayCache 实现自己的令牌重放检测功能,然后在配置文件中使用如下代码引用该功能。

<system.identityModel>
  <identityConfiguration>
    <tokenReplayDetection>
      <replayCache type='FQTN of your type' />
    </tokenReplayDetection>
  </identityConfiguration>
</system.identityModel>

将 wsFederation 的 requireHttps 属性设置为 true

requireHttps 属性控制该模块是否将只重定向 STS 的安全 URL。 默认值为“true”。 这可确保通过干净的 HTTPS/SSL 流量与 STS 安全通信,从而降低通过线路探查凭据和令牌的威胁。

例如:

<federatedAuthentication>
  <wsFederation
        passiveRedirectEnabled="true"
        issuer="http://STS URL GOES HERE/"
        realm="http://RP REALM GOES HERE/"
        requireHttps="ture" />
  <cookieHandler requireSsl="true" />
</federatedAuthentication>

将 cookieHandler 的 requireSsl 属性设置为 true

此值是布尔值;默认值为 false。 requireSsl 属性控制是否针对任何已编写 Cookie 发出“安全”标志。 如果设置了此值,则将只能通过 HTTPS 来访问登录会话 Cookie。 这可防止通过干净的流量发送会话 Cookie,从而降低通过线路探查令牌的威胁。

例如:

<federatedAuthentication>
  <wsFederation
        passiveRedirectEnabled="true"
        issuer="http://STS URL GOES HERE/"
        realm="http://RP REALM GOES HERE/"
        requireHttps="ture" />
  <cookieHandler requireSsl="true" />
</federatedAuthentication>

为 sessionTokenRequirement 的生存期属性设置主动值

考虑要求令牌在颁发时具有主动生存期限制。 当令牌被盗时,这可限制攻击者重放令牌的时间范围。

例如:

<add type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler, Microsoft.IdentityModel">
  <sessionTokenRequirement securityTokenCacheType="Microsoft.IdentityModel.MruSecurityTokenCache, Microsoft.IdentityModel"
                           saveBootstrapTokens="true"
                           securityTokenCacheSize="500"
                           useWindowsTokenService="false"
                           lifetime="10:00" />
</add>

列出 issuerNameRegistry 中的受信任 STS(令牌颁发者)

所有颁发者令牌都使用 IssuerNameRegistry 进行验证。 IssuerNameRegistry 的用途是将颁发者令牌映射到一个字符串名称。 如果验证失败,则不会接受令牌。 这会降低接受不受信任令牌的威胁。 可以使用 issuerNameRegistry> 元素的类型<属性注册任何自定义类型。 <issuerNameRegistry> 可以有一个子元素,该元素将用作 IssuerNameRegistry 的自定义配置。 提供了一种现成的 IssuerNameRegistry 类型(即 ConfigurationBasedIssuerNameRegistry),该类型可用于在配置中配置一组受信任的颁发者证书。 此类型需要配置受信任的颁发者证书的子配置元素 <trustedIssuers> 。 <trustedIssuers> 配置使用 ASN.1 编码形式的证书指纹添加受信任的证书。

例如:

<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel">
  <trustedIssuers>
    <add thumbprint="97249e1a5fa6bee5e515b82111ef524a4c9158de" name="contoso.com" />
    <remove thumbprint="97249e1a5fa6bee5e515b82111ef524a4c9158de" />
    <clear/>
  </trustedIssuers>
</issuerNameRegistry>

仅使用 audienceUri 将令牌的范围限于应用程序

<audienceUris> 指定识别此信赖方可接受的 URI 集。 除非已针对允许的某个受众 URI 确定了令牌的范围,否则不会接受令牌。 这将降低重放有效令牌的威胁,这些有效令牌是针对其他信赖方颁发的。 默认情况下,不会将任何 URI 添加到该集合。 SAML 1.1 和 SAML 2.0 令牌类型的 SecurityTokenHandler 使用该集合中的值在 SamlSecurityTokenRequirement 对象中配置任何允许的受众 URI 限制。

例如:

<audienceUris>
  <clear/>
  <add value="http://www.example.com/myapp/" />
  <remove value="http://www.example.com/myapp/" />
</audienceUris>

下面是与 ACS 管理门户配置相关的安全准则。

  • 为 STS 令牌设置主动过期

  • 在使用错误 URL 功能时提供足够的数据验证

  • 对于高度敏感的方案,考虑加密令牌

为 STS 令牌设置主动过期

令牌生存期属性控制令牌的生存期。 使用 ACS 门户或管理服务创建或配置信赖方时,会指定它。 可以使用 Token Lifetime 属性指定 ACS 向信赖方应用程序颁发的安全令牌保持有效的时间量。 默认情况下,在 ACS 中,此值设置为 10 分钟, (600 秒) 。 在 ACS 中,此值必须大于零,但小于或等于 24 小时, (86400 秒) 。

在使用错误 URL 功能时提供足够的数据验证

可以使用错误 URL 指定 ACS 在登录过程中发生错误时将用户重定向到的 URL。 它可以是托管在信赖方应用程序的自定义页面,例如 http://www.fabrikam.com/billing/error.aspx。 作为重定向的一部分,ACS 将有关错误的详细信息作为 JSON 编码的 HTTP URL 参数提供给信赖方应用程序。 可以制作自定义错误页,以使用 JSON 编码的错误信息呈现收到的实际错误消息或显示静态帮助文本。 如果页面需要授权,则结果将是无限重定向循环,在这种情况下,ACS 将尝试访问它并发送 JSON 编码错误。 因此,应将其配置为匿名访问。 由于该页可以匿名访问,并可能包含回显 HTML 或将数据写入到数据库的代码,因此你应采取措施以防止跨站点脚本和 SQL 注入式攻击。

对于高度敏感的方案,考虑加密令牌

对于被动联合的高度敏感的方案,请考虑加密令牌。 详细了解如何在 证书和密钥 主题中加密和解密令牌。

以下是与使用 ACS 且部署到 Azure 的应用程序相关的安全注意事项。

  • 使用 RSA 加密 Cookie

使用 RSA 加密 Cookie

在 Azure 中,默认 Cookie 加密机制(使用数据保护应用程序编程接口 (DPAPI))不适用,因为每个实例都有一个不同的密钥。 这意味着,一个 Web 角色实例将无法读取另一个 Web 角色实例创建的 Cookie。 这可能会导致服务失败,从而导致拒绝服务。 以下是你在使用默认 Cookie 加密机制时将遇到的错误消息:

[CryptographicException: Key not valid for use in specified state.
]
System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) +577
Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) +80
[InvalidOperationException: ID1073: A CryptographicException occurred when attempting to decrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ]
Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded) +433
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +189
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +862
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +109
Microsoft.IdentityModel.Web.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +356
Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +123
Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +61
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270

若要解决此问题,请在使用 Cookie 加密机制时,使用由所有 Web 角色实例共享的密钥。 下面的代码演示如何替换默认的 SessionSecurityHandler 对象,并将其配置为使用 RsaEncryptionCookieTransform 类。

private void OnServiceConfigurationCreated(object sender, 
    ServiceConfigurationCreatedEventArgs e)
{
    List<CookieTransform> sessionTransforms =
        new List<CookieTransform>(
            new CookieTransform[] 
            {
                new DeflateCookieTransform(), 
                new RsaEncryptionCookieTransform(
                    e.ServiceConfiguration.ServiceCertificate),
                new RsaSignatureCookieTransform(
                    e.ServiceConfiguration.ServiceCertificate)  
            });
   SessionSecurityTokenHandler sessionHandler = 
    new
     SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

    e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(
        sessionHandler);
}

void Application_Start(object sender, EventArgs e)
{
    FederatedAuthentication.ServiceConfigurationCreated += OnServiceConfigurationCreated;
}

其他资源