集成 Windows 身份验证与扩展保护

进行了可影响以下类处理集成式 Windows 身份验证的方式的改进:HttpWebRequestHttpListenerSmtpClientSslStreamNegotiateStream 以及 System.Net 和相关命名空间中的相关类。 添加了对扩展保护的支持,以提高安全性。

这些更改可能会影响使用这些类的应用程序发出 Web 请求并接收使用集成 Windows 身份验证的响应。 此更改还会影响配置为使用集成 Windows 身份验证的 Web 服务器和客户端应用程序。

这些更改还会影响使用这些类的应用程序发出其他类型的请求,并接收使用集成 Windows 身份验证的响应。

支持扩展保护的更改仅适用于 Windows 7 和 Windows Server 2008 R2 上的应用程序。 扩展保护功能在早期版本的 Windows 上不可用。

概述

集成 Windows 身份验证的设计允许某些凭据质询响应是通用的,这意味着可以重用或转发它们。 质询响应至少应与目标特定的信息一起构造,最好还包含一些通道特定的信息。 然后,服务可以提供扩展保护,以确保凭据质询响应包含服务主体名称(SPN)等特定于服务的信息。 在凭据交换中提供此信息后,服务能够更好地防范凭据质询响应的恶意使用,这些响应可能已被不当使用。

扩展保护设计是对身份验证协议的增强,旨在缓解身份验证中继攻击。 它围绕通道和服务绑定信息的概念展开。

总体目标是:

  1. 如果客户端已更新以支持扩展保护,则应用程序应向所有支持的身份验证协议提供通道绑定和服务绑定信息。 仅当有要绑定到的通道(TLS)时,才能提供通道绑定信息。 应始终提供服务绑定信息。

  2. 正确配置的更新服务器可能会在客户端身份验证令牌中存在通道和服务绑定信息时验证通道和服务绑定信息,并在通道绑定不匹配时拒绝身份验证尝试。 根据部署方案,服务器可以验证通道绑定、服务绑定或同时验证这两者。

  3. 更新的服务器能够接受或拒绝不包含基于策略的通道绑定信息的下层客户端请求。

扩展保护使用的信息包括以下两个部分之一或两个部分:

  1. 通道绑定令牌(Channel Binding Token,简称CBT)。

  2. 服务主体名称(即 SPN)形式的服务绑定信息。

服务绑定信息表明客户端打算向特定服务终结点进行身份验证。 它通过以下属性从客户端到服务器进行通信:

  • SPN 值必须可用于以明文形式执行客户端身份验证的服务器。

  • SPN 的值是公共的。

  • SPN 必须在传输中受到加密保护,这样中间人攻击无法插入、删除或修改其值。

CBT 是外部安全通道(如 TLS)的一项属性,用于通过内部客户端身份验证通道将其绑定到会话。 CBT 必须具有以下属性(也由 IETF RFC 5056 定义):

  • 当存在外部通道时,CBT 的值必须是一个标识外部通道或服务器终结点的属性,并且由会话的客户端和服务器端各自独立确定。

  • 客户端发送的 CBT 值不得是攻击者可能影响的内容。

  • 不保证 CBT 值的保密性。 但这并不意味着服务绑定和通道绑定信息的值始终可由执行身份验证的服务器之外的任何其他服务器检查,因为携带 CBT 的协议可能对其进行加密。

  • CBT 必须在传输中受到加密完整性保护,以便攻击者无法插入、删除或修改其值。

通道绑定由客户端以防篡改方式将 SPN 和 CBT 传输到服务器来完成。 服务器根据其自身策略验证通道绑定信息,并拒绝那些其不认为自己是预期目标的身份验证尝试。 这样,这两个通道就会在加密上绑定在一起。

为了保持与现有客户端和应用程序的兼容性,可以将服务器配置为允许尚不支持扩展保护的客户端尝试身份验证。 这称为“部分强化”配置,与“完全强化”配置形成鲜明对比。

命名空间System.NetSystem.Net.Security中的多个组件代表调用应用程序执行集成 Windows 身份验证。 本部分介绍 System.Net 组件的更改,以在其使用集成 Windows 身份验证时添加扩展保护。

Windows 7 目前支持扩展保护。 提供了一种机制,以便应用程序可以确定作系统是否支持扩展保护。

更改以支持扩展保护

身份验证与集成式 Windows 身份验证一起使用时,其过程通常包括由目标计算机发出质询并将质询发送回客户端计算机,具体取决于使用的身份验证协议。 扩展保护将新功能添加到此身份验证过程

命名空间 System.Security.Authentication.ExtendedProtection 支持使用应用程序的扩展保护进行身份验证。 ChannelBinding此命名空间中的类表示通道绑定。 ExtendedProtectionPolicy此命名空间中的类表示服务器用于验证传入客户端连接的扩展保护策略。 其他类成员用于扩展保护。

对于服务器应用程序,这些类包括:

具有以下元素的 A ExtendedProtectionPolicy

  • 一个 OSSupportsExtendedProtection 属性,指示作系统是否支持具有扩展保护的集成 Windows 身份验证。

  • 一个 PolicyEnforcement 值,该值指示何时应强制实施扩展保护策略。

  • ProtectionScenario 值,指示部署方案。 这会影响扩展保护的检查方式。

  • 可选的 ServiceNameCollection,其中包含自定义 SPN 列表,该列表用于根据客户端提供的作为身份验证预期目标的 SPN 进行匹配。

  • 一个可选 ChannelBinding ,其中包含用于验证的自定义通道绑定。 此方案不是常见情况

命名空间 System.Security.Authentication.ExtendedProtection.Configuration 支持使用应用程序的扩展保护配置身份验证。

进行了多项功能更改,以支持现有 System.Net 命名空间中的扩展保护。 这些更改包括:

进行了功能更改以支持现有 System.Net.Mail 命名空间中 SMTP 客户端应用程序的扩展保护:

  • TargetName 类中的 SmtpClient 属性,在为 SMTP 客户端应用程序使用扩展保护时表示用于身份验证的 SPN。

进行了多项功能更改,以支持现有 System.Net.Security 命名空间中的扩展保护。 这些更改包括:

添加了一个 SmtpNetworkElement 属性,以支持为命名空间中的 System.Net.Security SMTP 客户端配置扩展保护。

客户端应用程序的扩展保护

大多数客户端应用程序的扩展保护支持会自动发生。 每当基础版本的 Windows 支持扩展保护时,这些 HttpWebRequestSmtpClient 类都支持扩展保护。 HttpWebRequest 实例发送从 Uri 构造的 SPN。 默认情况下, SmtpClient 实例发送从 SMTP 邮件服务器的主机名构造的 SPN。

对于自定义身份验证,客户端应用程序可以使用HttpWebRequest.EndGetRequestStream(IAsyncResult, TransportContext)类中的HttpWebRequest.GetRequestStream(TransportContext)HttpWebRequest方法,这些方法允许使用TransportContext方法检索GetChannelBinding和CBT。

通过设置 HttpWebRequest 属性,可重写 CustomTargetNameDictionary 实例向给定服务发送集成式身份验证所用的 SPN。

TargetName 属性可用于设置用于 SMTP 连接的集成 Windows 身份验证的自定义 SPN。

服务器应用程序的扩展保护

HttpListener 自动提供在执行 HTTP 身份验证时验证服务绑定的机制。

最安全的方案是为前缀启用扩展保护 HTTPS:// 。 在这种情况下,将HttpListener.ExtendedProtectionPolicy设置为一个ExtendedProtectionPolicy,将PolicyEnforcement设置为WhenSupportedAlways,并将ProtectionScenario设置为TransportSelected。设置为WhenSupported的值将使HttpListener处于部分强化模式,而设置为Always则对应于完全强化模式。

在此配置中,当通过外部安全通道向服务器发出请求时,会查询外部通道进行通道绑定。 此通道绑定将传递给身份验证 SSPI 调用,该调用验证身份验证 Blob 中的通道绑定是否匹配。 有三种可能的结果:

  1. 服务器的基础作系统不支持扩展保护。 请求不会向应用程序公开,并且未经授权的 (401) 响应将返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

  2. SSPI 调用失败,指示客户端指定了与从外部通道检索到的预期值不匹配的通道绑定,或者当服务器上配置 Always扩展保护策略时,客户端无法提供通道绑定。 在这两种情况下,请求都不会向应用程序公开,并且未经授权的 (401) 响应将返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

  3. 客户端指定正确的通道绑定,或者允许在没有指定通道绑定的情况下进行连接,因为服务器上已配置 WhenSupported 扩展保护策略,请求将返回到应用程序进行处理。 不会自动执行任何服务名称检查。 应用程序可以选择使用 ServiceName 属性执行自己的服务名称验证,但在这种情况下,它是冗余的。

如果应用程序发出自己的 SSPI 调用以基于 HTTP 请求正文中来回传递的 Blob 执行身份验证,并且希望支持通道绑定,则需要从 HttpListener 外部安全通道检索预期的通道绑定,以便将其传递给本机 Win32 AcceptSecurityContext 函数。 为了做到这一点,请使用 TransportContext 属性并调用 GetChannelBinding 方法来检索 CBT。 仅支持终结点绑定。 如果指定除 Endpoint 外的其他内容,将引发 NotSupportedException。 如果基础操作系统支持通道绑定,GetChannelBinding 方法将返回 ChannelBindingSafeHandle,包装指向适合传递到 AcceptSecurityContext 函数的通道绑定的指针,因为 SecBuffer 结构的 pvBuffer 成员传入了 pInput 参数。 该 Size 属性包含通道绑定的长度(以字节为单位)。 如果基础作系统不支持通道绑定,该函数将返回 null

另一种可能的方案是在不使用代理时为 HTTP:// 前缀启用扩展保护。 在这种情况下,将HttpListener.ExtendedProtectionPolicy设置为一个ExtendedProtectionPolicy,将PolicyEnforcement设置为WhenSupportedAlways,并将ProtectionScenario设置为TransportSelected。设置为WhenSupported的值将使HttpListener处于部分强化模式,而设置为Always则对应于完全强化模式。

基于已向 HttpListener 注册的前缀创建允许的服务名称的默认列表。 可以通过DefaultServiceNames 属性检查此默认列表。 如果此列表不全面,应用程序可以在将使用该类的构造函数 ExtendedProtectionPolicy 中指定自定义服务名称集合,而不是默认服务名称列表。

在此配置中,在没有外部安全通道身份验证的情况下向服务器发出请求时,通常不会进行通道绑定检查。 如果身份验证成功,则会针对客户端提供的服务名称查询上下文,并针对可接受的服务名称列表进行验证。 有四种可能的结果:

  1. 服务器的基础作系统不支持扩展保护。 请求不会向应用程序公开,并且未经授权的 (401) 响应将返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

  2. 客户端的基础作系统不支持扩展保护。 在配置中 WhenSupported ,身份验证尝试将成功,请求将返回到应用程序。 在配置中 Always ,身份验证尝试将失败。 请求不会向应用程序公开,并且未经授权的 (401) 响应将返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

  3. 客户端的基础作系统支持扩展保护,但应用程序未指定服务绑定。 请求不会向应用程序公开,并且未经授权的 (401) 响应将返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

  4. 客户端指定了服务绑定。 服务绑定与允许的服务绑定列表进行比较。 如果匹配,则请求将返回到应用程序。 否则,请求不会向应用程序公开,并且未经授权的 (401) 响应将自动返回到客户端。 将向跟踪源记录 HttpListener 消息,指定失败原因。

如果使用此允许的服务名称列表的简单方法不足,则应用程序可以通过查询 ServiceName 属性来提供自己的服务名称验证。 如果上面有 1 和 2,则属性将返回 null。 如果为 3,它将返回一个空字符串。 如果为 4,将返回客户端指定的服务名称。

这些扩展保护功能也可由服务器应用程序用于其他请求类型的、使用了受信任代理时的身份验证。

另请参阅