IIS 6.0 与 IIS 7 及更高版本之间的安全性更改

作者:IIS 团队

介绍

IIS 7 及更高版本在 IIS 6.0 的基础上对安全性进行了许多新的改进。 本文档概述了有关身份验证、授权、SSL、Web 服务扩展限制列表和 IP 限制的这些改进。

身份验证

对于 ASP.NET 应用程序开发人员来说,在 IIS 7 之前,需要针对两种身份验证模型进行编程。 这些模型是 IIS 和 ASP.NET 管道。 首先,IIS 会检查请求并执行其身份验证例程,然后将其传递给 ASP.NET,以便其执行类似任务。

在 IIS 7 及更高版本中,我们统一了这两种模型,以生成一个新的可靠管道,该管道可以发挥两种旧模型的最佳性能。 IIS 仍支持所有旧身份验证协议,但现在还支持表单身份验证,后者可以防范所有内容类型,并且不依赖于 Windows 帐户。 除了支持你了解和热爱的所有旧功能之外,我们还增强了其中一些功能,例如匿名身份验证功能。

接下来的部分将讨论这些更改。

匿名身份验证更改

在 IIS 7 及更高版本中,匿名身份验证的行为方式与以前版本中类似,只有一项更改,即能够在工作进程标识的内容下运行。 每个应用程序池都配置为在用户帐户的内容下运行,此帐户的默认值为 NETWORKSERVICE。

对于 ASP.NET 应用程序来说,通过在其 web.config 文件中使用以下代码来关闭模拟并在应用程序池标识下运行是很常见的:

<identity impersonate="false"/>

在多种情况下,应用程序需要在进程标识的上下文下运行:

  • 进程标识是低特权帐户,管理员已锁定该帐户的系统
  • 进程标识已被授予网络访问权限,并用于访问数据库等后端资源

作为 IIS 7 及更高版本重新设计工作的一部分,我们希望使此方案安全且易于实现。 为了实现此方案,需要在 IIS 中:

  • 安装和启用匿名身份验证模块
  • 将匿名用户名和密码设置为空字符串

为此,请修改匿名身份验证的配置,使其如下所示:

<anonymousAuthentication enabled="true" userName="" defaultLogonDomain="" />

此配置将告知 IIS 始终在工作进程标识的上下文下运行。

默认情况下,IIS 7.0 及更高版本中的匿名身份验证标识是 IUSR 帐户。 此帐户是一个低特权标识,具有最小的权限和特权。 要详细了解新内置帐户,请参阅了解 IIS 7 及更高版本中的内置帐户和组一文。

Passport 更改

IIS 5/6 以及 Windows Server 2000 和 2003 中内置了对旧版 Passport 身份验证的支持。 IIS 5 和 6 中的 Passport 支持在 IIS 服务管理器的“目录安全”选项卡中显示为“启用 Passport 身份验证”复选框。 此复选框使 IIS 能够发送旧版 Tweener 协议质询。 除此之外,仍然需要向 Passport 服务预配门户注册网站、获取加密密钥并在服务器上配置旧版 Passport Manager,然后 IIS 集成才能正常运行。

在 Windows Server 2008 及更高版本中,移除了旧版 Passport 二进制文件和与 IIS 的集成。

Passport 服务此后已更改为 Windows Live ID。 虽然新的 Live ID 服务无疑从旧版 Passport 服务发展而来的,但也有重大变化。 最大的变化之一是合作伙伴网站与 Live ID 的集成方式。 可以使用公开提供的 Windows Live ID Web 身份验证 SDK 添加 Live ID 身份验证。 虽然 Windows Live ID 服务还支持标识联合身份验证和 ADFS,但该功能是特定情况的新功能,而不能替代“Passport”。

窗体身份验证

表单身份验证已成为 ASP.NET 的一部分,允许 Windows 和非 Windows 标识对自身进行身份验证,并获取应用程序稍后可以使用的用户对象。 IIS 7 及更高版本现在完全支持表单身份验证,并且可以配置为保护对所有内容类型的访问。

IIS 7 及更高版本如何确定经过身份验证的标识

在 IIS 7 及更高版本中,核心引擎处理身份验证规则的方式与以前版本的 IIS 中类似,仅进行了一些细微的更改。 为了更好地了解处理顺序,下面基于 IIS 的评估顺序列出了规则:

  • 首先,IIS 确定虚拟目录中是否配置了用户名和密码。 如果已定义一组凭据,则使用这些凭据。 对于 IIS 7 之前的管理员,这些凭据是 UNC 凭据
  • 如果虚拟目录中未配置凭据,则 IIS 使用身份验证期间提供的凭据。 这些凭据可以属于为匿名身份验证配置的标识,或属于在启用基本、摘要或 Windows 身份验证时用户在身份验证握手期间提供的凭据
  • 如果未建立经过身份验证的用户(例如已启用表单身份验证),我们将确定是否应使用进程标识
  • 如果此时没有标识,则 IIS 返回拒绝访问

授权

AzMan 支持

在 IIS 6.0 中,我们引入了基于 AZMan 规则的新授权模型。 在 IIS 7 及更高版本中,我们已弃用此功能,转而采用与 ASP.NET 授权模型非常相似的新模型(请参阅下面的 URL 授权主题)。

URL 授权

在 IIS 7 及更高版本中,有两个授权解决方案。 第一个是使用 ASP.NET 授权模型。 此方法需要在 <system.web> 配置中定义所有授权规则,并且需要不对已具有为 ASP.NET 编写的规则的应用程序进行任何更改。 第二个模型是迁移到新的 IIS 授权体系结构。 该模型与 ASP.NET 的模型非常相似,但有一些细微更改:

  • 规则与顺序无关
  • 拒绝规则排在列表顶部
  • 规则的处理方式与 ASP.NET 相反,主要是按以下顺序:祖父级,父级,然后是子级;ASP.NET 授权以相反的顺序处理规则:子级、父级、然后是祖父级

为了更好地理解 ASP.NET 授权模型与 IIS 授权模型之间的差异,让我们先看看 ASP.NET 授权配置:

<authorization>
    <allow users="Vik_Malhotra" />
    <deny roles="administrators" />
    <deny users="*" />
</authorization>

在此示例中,我们允许 Vik_Malhotra,但拒绝所有其他人。 在 IIS 中,配置非常相似:

<authorization>
    <add accessType="allow" users="Vik_Malhotra" />
    <add accessType="deny" roles="administrators" />
    <add accessType="deny" users="*" />
</authorization>

语法更改的原因在于,我们希望确保应用程序开发人员知道这两种模型实际上是不同的,但同时他们可以轻松将规则从一种实现转移到另一种实现。

SSL

在 IIS 6.0 中,IIS 将 SSL 相关信息存储在元数据库中,并与 HTTP.SYS 一起管理大部分 SSL 协商过程。 在 IIS 7 及更高版本中,我们已将大部分此配置移到 HTTP.SYS 的存储中。

为了说明每个 IIS 6.0 配置设置如何沿用到 IIS 7 及更高版本的配置(或 HTTP.SYS 配置),构建了以下图表。

IIS 6.0 元数据库配置 属性说明 IIS 7.0 及更高版本体系结构
AccessSSLFlags AccessSSLFlags 是 AccessSSL 的位掩码 AccessSSL128 AccessSSLNegotiateCert AccessSSLRequireCert AccessSSLMapCert 值为 0 表示没有 SSL IIS 7.0 及更高版本配置的 <access> 部分中仍然支持该属性
CertCheckMode 启用或禁用 CRL(证书吊销列表)检查。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
RevocationFreshnessTime 如果 RevocationFreshnessTime 属性设置为 1 (true),则证书客户端上的证书吊销列表 (CRL) 由 CRL 从远程位置进行更新,即使证书客户端上缓存的 CRL 有效也是如此。 默认超时间隔为一天,除非使用 RevocationURLRetrievalTimeout 指定其他超时间隔(以分钟为单位)。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SecureBindings SecureBindings 属性指定一个字符串,IIS 使用该字符串来确定服务器实例使用的安全网络终结点。 在 IIS 7.0 及更高版本配置中,<sites> 的 <binding> 部分下仍然支持此属性。 使用的协议需要为“https”。
SSLAlwaysNegoClientCert SSLAlwaysNegoClientCert 属性控制 SSL 客户端连接协商。 如果此属性设置为 true,则每次协商 SSL 连接时,服务器都会立即协商客户端证书,从而防止代价高昂的重新协商。 设置 SSLAlwaysNegoClientCert 还有助于消除客户端证书重新协商死锁,在收到重新协商请求时,若客户端在发送大型请求正文时被阻止,则可能会发生这种死锁。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SSLCertHash SSLCertHash 属性用于存储正在使用的 SSL 证书的哈希。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SslCtlIdentifier SslCtlIdentifier 属性包含标识特定证书信任列表 (CTL) 的唯一值。 它必须与 SslCtlStoreName 一起使用才能准确引用 CTL。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SslCtlStoreName SslCtlStoreName 属性包含含有证书信任列表 (CTL) 的 CryptoAPI 存储的名称。 它必须与 SslCtlIdentifier 一起使用才能准确引用 CTL。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SSLStoreName SSLStoreName 属性用于存储证书密钥对所在的存储的名称。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。
SslUseDsMapper SslUseDsMapper 属性指定 IIS 是使用 Windows 目录服务证书映射程序还是 IIS 证书映射程序。 如果 SSLUseDSMapper 设置为 false,则 IIS 使用 IIS 证书映射程序。 该值现在存储在 http.sys 的 PHTTP_SERVICE_CONFIG_SSL_PARAM 对象中。

有关 HTTP.SYS PHTTP_SERVICE_CONFIG_SSL_PARAM 对象的详细信息,请参阅以下文档

所有这些更改都以透明方式在后台进行处理,因此服务器管理员无需执行任何特殊操作,IIS 会完成所有操作。 如果应用程序正在访问现在位于 HTTP.SYS 配置存储中的旧 IIS 6.0 属性,我们的 ABO 映射程序接口可确保读取/写入正确的值,使应用程序不会失败,而是继续工作。

Web 服务扩展限制列表

在 IIS 7 及更高版本中,此功能经过小幅修改,其名称现在为“isapiCgiRestrictionList”,但在其他方面,其表现和行为与在 IIS 6.0 中相同

进行此更改的原因是为了强调其真实用途。 在 IIS 6.0 中,添加此功能是为了确保未授权的 ISAPI 或 CGI 二进制文件无法复制到 IIS 服务器并随后被允许执行。 通过针对 IIS 7 及更高版本进行重新设计,我们提供了两个受支持的模型:

  • “经典”ISAPI 管道
  • 新的集成管道

如果我们位于“经典”ISAPI 管道中,所有内容都会像使用 IIS 6.0 时预期的那样继续工作。 为了说明这一点,请考虑在 ISAPI 模式下运行时,ASP.NET 的工作原理。 首先,需要添加 aspnet_isapi.dll 的完整路径,并将其设置为 allowed="true",如下所示:

<isapiCgiRestriction>
    <add path="F:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"
    allowed="true" groupId="ASP.NET v2.0.50727" description="ASP.NET v2.0.50727" />
</isapiCgiRestriction>

现在且只有现在才允许执行此代码 (aspnet_isapi.dll)。 如果我们将管道模式切换为集成并更改为 allowed="false",仍将执行 ASP.NET 代码。

为什么? 原因是 isapiCgiRestrictionList 仅适用于 ISAPI 和 CGI 代码。 在集成模式下,ASP.NET 现在是新体系结构的一部分,因此不受 isapiCgiRestrictionList 的影响。 如果不想在新的集成管道中运行 ASP.NET 代码,只需从模块列表中移除 managedEngine 即可。

IP 限制

IP 限制的工作方式与过去完全相同,只是我们现在支持名为“allowUnlisted”的新属性。 添加此属性是为了更轻松地在全局级别为系统配置安全策略。 例如,如果策略要求只允许某些 IP 地址,但拒绝所有未列出的其他 IP 地址,这在过去并不容易做到。 同样,现在可以轻松地仅拒绝一组给定的 IP 地址并允许所有未列出的 IP 地址。 服务器管理员可以设置全局策略,然后锁定此值,使应用程序或站点管理员无法在服务器上更改它。

为了对此进行说明,请考虑使用仅希望用户在本地访问的开发计算机。 以下配置通过设置 allowUnlisted="false" 来实现该策略,然后显式仅允许本地主机 (127.0.0.1) 访问:

<system.webServer>
    <security>
        <ipSecurity allowUnlisted="false">
            <add ipAddress="127.0.0.1" allowed="true" />
        </ipSecurity>
    </security>
</system.webServer>