[转载]保护 ASP.NET 应用程序的安全
Microsoft Corporation
![*](http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif)
本单元概要
保护 ASP.NET Web 应用程序依赖于完全受到保护的网络、主机和平台基础结构。如果果真如此,攻击者将试图利用 Web 应用程序和 Web 服务(它们通常侦听端口 80)中的漏洞。如果 Web 应用程序没有有效配置,攻击者就能够获取访问权限并利用系统。
作为管理员,您必须审查默认的机器级配置和单独的应用程序配置,以处理和删除任何脆弱或者不安全的设置。
本单元从系统管理员的观点描述了 ASP.NET 的新功能,以及如何配置机器范围的和特定于应用程序的安全设置。还提出了一种保护 ASP.NET Web 应用程序和 Web 服务的方法,它对我们已经提出的保护网络、应用程序服务器、数据库服务器和 Web 服务器的方法是一种补充。
目标
使用本单元可以:
• |
在注册表中使用 Aspnet_setreg.exe 实用工具存储凭据和连接字符串。 |
• |
使用配置文件 (*.config) 管理 Web 应用程序环境。 |
• |
了解如何层次化地实施和处理 Machine.Config 和 Web.Config。 |
• |
锁定配置设置。 |
• |
实施机器范围的和 Web 应用程序的安全策略。 |
• |
通过使用 元素自定义文件和目录安全设置。 |
• |
保护 ASP.NET 进程标识和在 ASP.NET 应用程序中使用自定义模拟。 |
• |
了解 ASP.NET 进程帐户必需的 NTFS 权限。 |
• |
使用窗体身份验证和 URL 授权保护资源。 |
• |
保护 ASP.NET 会话状态的安全。 |
• |
保护 Web 服务器场的安全并保护 Bin 目录。 |
适用范围
本单元适用于下列产品和技术:
• |
Microsoft® Windows® Server 2000 操作系统 |
• |
Microsoft .NET Framework 1.1 和 ASP.NET 1.1 |
• |
Microsoft SQL Server™ 2000 |
如何使用本单元
本单元的注意力主要集中在 ASP.NET 应用程序的关键安全注意事项。要想充分利用本单元:
• |
阅读单元“保护 Web 服务器的安全”。该单元说明了如何保护 Windows 2000 操作系统和 Microsoft .NET Framework。安全的基础平台是保护 ASP.NET Web 应用程序或者 Web 服务的前提条件。 |
• |
使用快照。本单元最后的表 4 提供了带有 Machine.config 和 Web.config 中的安全配置设置的安全 ASP.NET 应用程序的快照。在配置服务器和应用程序设置时应该使用此表。 |
• |
使用核对表。本指南“核对表”部分中的“核对表:保护 ASP.NET 的安全”,提供了可以打印的快速参考工具。使用基于任务的核对表,可以快速评估必需步骤的范围,帮助您完成各个步骤。 |
相关的指导,请阅读“寄宿多个 ASP.NET 应用程序”单元,该单元说明了如何将多个运行在同一服务器上的 Web 应用程序与关键系统资源隔离,以及将应用程序互相隔离。有关为部分信任 Web 应用程序和 Web 服务配置代码访问安全 (CAS) 策略的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。
本页内容
方法
要保护 ASP.NET 应用程序的安全,首先要有加固的操作系统和 .NET Framework 安装基础,然后应用安全应用程序配置设置,以减少应用程序的受攻击面。
这些内容包括:
• |
服务。.NET Framework 安装 ASP.NET 状态服务以管理进程外的 ASP.NET 会话状态。 如果您安装了 ASP.NET 状态服务,就应该保护它。如果您不需要,则应该禁用 ASP.NET 状态服务。 |
• |
协议。限制 Web 服务协议以减少受攻击面。 |
• |
帐户。默认 ASPNET 帐户是为运行 Web 应用程序、Web 服务和 ASP.NET 状态服务而创建的。如果您创建自定义帐户运行进程或者服务,则必须配置为最低特权帐户,只具有最小集合的必需 NTFS 权限和 Windows 特权。 |
• |
文件和目录。用来存储私有程序集的应用程序 Bin 目录应该进行保护,以降低攻击者下载业务逻辑的风险。 |
• |
配置存储区。许多控制功能区域(如身份验证、授权、会话状态等等)与安全相关的设置,都在 Machine.Config 和 Web.Config XML 配置文件中维护。要保护 ASP.NET 应用程序的安全,必须使用安全配置设置。 |
须知
在开始保护 Web 应用程序和 Web 服务之前,应该知道一些涉及全局的注意事项和细节。
ASP.NET 进程模型
在 Microsoft Windows 2000 上,Internet 信息服务 (IIS) 5.0 在 ASP.NET 辅助进程 (Aspnet_wp.exe) 中运行所有 Web 应用程序和 Web 服务。隔离的单位是应用程序域,每个虚拟目录都有自己的应用程序域。进程级配置设置是通过 Machine.config 中的 <processModel> 元素维护的。
在 Microsoft Windows Server™ 2003 操作系统上,IIS 6.0 应用程序池使您能够使用不同的进程隔离应用程序。有关更多信息,请参阅单元“寄宿多个 ASP.NET 应用程序”。
ASP.NET 帐户
ASPNET 帐户是安装 .NET Framework 时创建的最低特权本地帐户。默认时,它运行 ASP.NET 辅助进程和 ASP.NET 状态服务。
如果您决定使用自定义帐户运行 Web 应用程序,确保配置帐户只具有最低特权。这将能够减少与攻击者使用应用程序的安全上下文设法执行代码相关联的风险。您还必须在 <processModel> 元素上指定帐户的凭据。千万不要以明文存储凭据。相反,应该使用 Aspnet_setreg.exe 工具在注册表中存储加密凭据。自定义帐户还必须被授予适当的 NTFS 权限。
Aspnet_setreg.exe 和进程、会话和身份
Aspnet_setreg.exe 允许在注册表中以加密格式存储凭据和连接字符串。此工具允许您加密以下属性:
• |
<processModel userName = password= /> |
• |
<identity userName = password= /> |
• |
<sessionState sqlConnectionString = stateConnectionString= /> |
下例显示了运行 Aspnet_setreg.exe 保护凭据前后,自定义帐户的 <processModel> 元素的变化:
<!--Before--> <processModel userName="CustomAccount" password="Str0ngPassword" /> <!--After--> <processModel userName="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,password"/>
您可以选择用来存储加密数据的注册表位置,虽然必须在 HKEY_LOCAL_MACHINE 之下。除了使用数据保护 API (DPAPI) 加密数据,并将其存储在注册表中之外,此工具还能够应用安全 ACL 限制对注册表项的访问。注册表项的 ACL 将向 System、Administrator 和 Creator Owner 授予完全控制权限。如果使用此工具加密 <identity> 元素的凭据或者 <sessionState> 元素的连接字符串,您还必须授予 ASP.NET 进程帐户的读访问权限。
要获取 Aspnet_setreg.exe 工具和有关的更多信息,请参阅 Microsoft 知识库文章 329290,“How To:Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings”。
模拟不是默认的
默认时,ASP.NET 应用程序不进行模拟。因此,资源访问是使用 ASP.NET 辅助进程标识进行的。您必须通过创建适当配置的 ACL 授予进程标识(至少)对 Windows 资源的读访问权限(这是应用程序要求的)。
如果您确实需要启用模拟,可以模拟原始调用方 — 即经 IIS 身份验证的标识或者 <identity> 元素中指定的固定标识。有关更多信息,请参阅本单元后面的“模拟”。
通常,ASP.NET 应用程序不使用模拟,因为这对设计、实现和可伸缩性有负面影响。例如,使用模拟妨碍有效的中间层连接池的使用,这限制了应用程序的可伸缩性。在特定的场景例如当应用程序使用匿名用户帐户的安全上下文进行资源访问时,模拟可能非常重要。这是一个常用技术,经常在多个应用程序寄宿在同一服务器时使用。有关更多信息,请参阅单元“寄宿多个 ASP.NET 应用程序”。
HttpForbiddenHandler、Urlscan 和 404.dll
您可以用许多技术来防止访问受限资源。ASP.NET 提供了 HttpForbiddenHandler,可以将不应该通过 HTTP 下载的 ASP.NET 文件类型映射为此处理程序。映射是使用 <httpHandlers> 元素应用的。
IISLockdown.exe 提供了404.dll。通过这个工具,您可以配置 IIS 将不希望的文件扩展名映射到 404.dll,这样在请求这些文件类型时,会导致“HTTP 404–File not found”消息。
最后,URLScan ISAPI 筛选器可以用来阻塞对受限文件类型和可执行程序文件的请求。URLScan 是 IISLockdown 工具中附带的,但是也可以单独获得。有关更多信息,请参阅 Microsoft 知识库文章 307608,“ INFO:Using URLScan on IIS”,和本指南“如何……”部分中的“如何使用 URLScan”。
有关 IISLockdown 和 URLScan 的更多信息,请参阅“保护 Web 服务器的安全”单元。
AppSettings
Web.config 中的 <appSettings> 元素允许应用程序存储配置数据,如数据库连接字符串或者服务帐户凭据。此元素的优点是,它允许开发人员将配置数据的存储和检索集中和标准化。Web.config 中的单一位置还能够简化管理和部署。
敏感数据,如连接字符串和凭据,不应该以明文形式存储在配置文件中。相反,开发人员应该在存储之前使用 DPAPI 加密机密。
有关 AppSettings 的更多信息,请参阅 MSDN® TV 上的“AppSettings in ASP.NET”节目,网址是:http://msdn.microsoft.com/msdntv。
Machine.Config 和 Web.Config 详解
.NET Framework 提供的配置管理包括范围很广的一组设置,可以供管理员用来管理 Web 应用程序及其环境。这些设置存储在 XML 配置文件中,其中一些控制着机器范围的设置,而其他设置控制着特定于应用程序的配置。
XML 配置文件可以使用任何文本编辑器(如记事本或者 XML 编辑器)编辑。XML 标记是区分大小写的,因此需要确保使用正确的大小写。
图 1 显示了用来配置管理员能够访问的 ASP.NET Web 应用程序的配置文件。
![](http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/ImpWebSec/art/f19secmod01.gif)
图 1. ASP.NET 配置文件
Machine.Config 和 Web.Config 文件共享许多相同的配置节和 XML 元素。Machine.config 用来将机器范围的策略应用于本地计算机上运行的所有 .NET Framework 应用程序。开发人员还可以使用特定于应用程序的 Web.config 文件为单独应用程序自定义设置。
注 Windows 可执行文件,如 WinForm 应用程序,是使用配置文件配置的。这些文件的名称从应用程序可执行文件名称派生而来,例如,App.exe.config,其中的 App 是应用程序名称。
对配置文件所做的更改是动态应用的,通常不需要您重启服务器或者任何服务,除非如果更改 Machine.config 中的 <processModel> 元素,这将在本单元后面讨论。
表 1 显示了配置文件的位置。
表 1 配置文件位置 | |
配置文件 | 位置 |
Machine.config |
%windir%\Microsoft.NET\Framework\{version}\CONFIG |
Web.config |
\inetpub\wwwroot\web.config |
Enterprisesec.config |
%windir%\Microsoft.NET\Framework\{version}\CONFIG |
Security.config |
%windir%\Microsoft.NET\Framework\{version}\CONFIG |
Security.config |
\Documents and Settings\{user}\Application Data\Microsoft\CLR Security Config\{version} |
Web_hightrust.config |
%windir%\Microsoft.NET\Framework\{version}\CONFIG |
有关 ASP.NET Web 应用程序 CAS 配置文件的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。
层次化策略评估
为了集中化管理,设置可以在 Machine.config 中应用。Machine.config 中的设置定义了机器范围的策略,还可以通过 <location> 元素使用 Machine.config 中的设置应用特定于应用程序的配置。开发人员可以提供应用程序配置文件以改写机器策略的各个方面。对于 ASP.NET Web 应用程序,Web.config 文件位于应用程序的虚拟根目录,也可以选择在虚拟根下的子目录。考虑如图 2 中所示的安排。
![](http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/ImpWebSec/art/f19secmod02.gif)
图 2. 层次化配置
在图 2 中,AppRoot Web 应用程序在其虚拟根目录中有一个 Web.config 文件。SubDir1(而非虚拟目录)还包含它自己的 Web.config 文件,在 HTTP 请求定向到 http://AppRoot/SubDir1 时会用到。如果请求通过 AppRoot 定向到 SubDir2(一个虚拟目录),例如,http://Server/AppRoot/SubDir2,则应用来自 AppRoot 目录中 Machine.config 和 Web.config 的设置。但是,如果请求绕过 AppRoot 而定向到 SubDir2,例如,http://Server/SubDir2,则只应用来自 Machine.config 的设置。
无论如何,基本设置都是从 Machine.config 获取的。接下来,从任何相关 Web.config 文件应用改写和添加。
如果在 Machine.config 中和一个或者多个 Web.config 文件中使用同一个配置元素,来自层次中最低的文件的设置将改写较高级的设置。在机器级没有应用的新配置设置也可能应用于 Web.config 文件,而且某些元素能够使用<clear >元素清除父级设置。
下表显示了为了应用于图 2 的 Web 请求的组合,从何处获取组合的配置设置。
表 2 应用配置设置 | |
HTTP 请求 | 组合设置获取自 |
http://Server/AppRoot |
Machine.config |
http://Server/AppRoot/SubDir1 |
Machine.config |
http://Server/AppRoot/SubDir2 |
Machine.config |
http://Server/Subdir2 |
Machine.config |
<location> 元素用于三个主要目标:
• |
为了将配置设置应用于特定的应用程序文件。 |
• |
为了通过应用 Machine.config 中的特定于应用程序的设置,实现集中化管理。 |
• |
为了锁定配置设置以防止在应用程序级改写。 |
<location> 标记可以用于 Machine.config 中或者 Web.config 中。对于 Machine.config,如果您指定了路径,则必须是完全限定的,包括 Web 站点名称、虚拟目录名称和可选的子目录和文件名。例如:
<location path="Web Site Name/VDirName/SubDirName/PageName.aspx" > <system.web> . . . </system.web> </location>
注 当使用来自 Machine.config 的位置标记时,您必须包括 Web 站点名称。对于 Web.config,路径相对于应用程序的虚拟目录。例如:
<location path="SubDirName/PageName.aspx" > <system.web> . . . </system.web> </location>
对特定的文件应用配置设置
使用 path 属性以应用特定文件的配置设置。例如,为了将授权规则应用于来自 Web.config 中的文件 Pagename.aspx,应该使用以下 <location> 元素:
<location path="SubDirName/PageName.aspx" > <system.web> <authorization> <deny roles="hackers" /> </authorization> </system.web> </location>
应用 Machine.config 中的应用程序配置设置
您还可以通过使用指定到应用程序目录路径的 <location>语句,应用 Machine.config 中的特定于应用程序的设置。这将使您得到集中化管理的优点。例如,以下片段显示了如何强制使用 Windows 身份验证和防止在特定的应用程序中使用模拟。
<location path="Default Web Site/YourApp"> <system.web> <authentication mode="Windows"/> <identity impersonate="false"/> </system.web> </location>
锁定配置设置
为了防止各个应用程序改写机器级策略配置,将设置置于 Machine.config 中的一个 <location> 元素里,并设置 allowOverride="false" 属性。
例如,为了应用无法在应用程序级改写的机器范围策略,使用以下 <location> 元素:
<location path="" allowOverride="false"> <system.web> … machine-wide defaults </system.web> </location>
通过将 path 属性置为空,可以指示设置应用于机器,而 allowOverride="false" 确保了 Web.config 设置不会改写指定的值。只要企图在 Web.config 中添加元素都将生成异常,即使 Machine.config 中的元素与 Web.config 中的元素匹配。
Machine.Config 和 Web.Config 准则
Machine.config 中的设置应用服务器的机器级默认值。如果需要强制服务器上所有应用程序应用一个特殊的配置,使用 <location> 元素的 allowOverride="false",如上所述。这对于寄宿场景尤其适合,其中需要强制服务器上所有应用程序应用安全策略的各个方面。
对于可以对单独应用程序配置的设置,通常应用程序会提供一个 Web.config 文件。虽然可能从 Machine.config 使用多个 <location> 元素配置单独应用程序,但是通过不同的 Web.config 文件对部署来说更佳,而且能够使 Machine.config 文件更小。
主要要考虑的项是哪些设置应该通过机器策略强制。这取决于特定的场景如何。以下是一些常见的场景:
• |
Windows 身份验证。考虑一个公司 intranet 门户场景,其中需要身份验证从应用程序中提取,并由一个单位通过 Active Directory 控制。在此场景,您可以强制 Windows 身份验证,但是允许单独的应用程序用以下配置模拟: <location path="" allowOverride="false"> <system.web> <authentication mode="Windows"/> </system.web> </location> |
• |
寄宿场景。寄宿公司需要约束应用程序,使它们无法访问彼此的资源,从而对关键系统资源只有有限的访问权限。为此,您可以配置所有应用程序为在部分信任级运行。例如,中度信任级将约束应用程序,使其只能访问自己虚拟目录层次中的文件,并限制对其他类型资源的访问。有关更多信息,请参阅单元“在 ASP.NET 中使用代码访问安全”。为了使服务器上所有应用程序应用中度信任策略,使用以下配置: <location path="" allowOverride="false> <system.web> <trust level="Medium" /> </system.web> </location> |
ACL 和权限
配置文件包含敏感数据,所以需要适当地配置 ACL 以限制访问。
Machine.config
默认时,Machine.config 使用以下 ACL 配置:
Administrators: Full Control System: Full Control Power Users: Modify Users: Read and Execute LocalMachine\ASPNET (process identity): Read and Execute
注 在 Windows Server 2003 上,本地服务和网络服务帐户也被授予读访问权限。
Users 组的成员默认时被授予读访问权限,因为所有运行在计算机上的托管代码必须能够读取 Machine.config。
Machine.config 上的默认 ACL 是一个安全默认值。但是,如果只有一个 Web 应用程序运行在服务器上,或者所有 Web 应用程序都使用同一个进程标识,可以通过删除用户的访问控制项 (ACE) 进一步限制 ACL。如果您确实从 DACL 中删除了“users”,需要显式地添加 Web 进程标识。
Web.config
.NET Framework 不安装任何 Web.config 文件。如果您安装了一个提供自己 Web.config 的应用程序,通常从 inetpub 目录继承其 ACL,它默认时授予 Everyone 组的成员读访问权限。要锁定特定于应用程序的 Web.config,使用以下的一个 ACL。
对于 .NET Framework 1.0 版:
Administrators: Full control System: Full control ASP.NET process identity: Read UNC Identity: Read Impersonated Identity (Fixed Identity): Read Impersonated Identity (Original Caller): Read
对于 .NET Framework 1.1 版:
Administrators: Full control System: Full control ASP.NET process identity: Read UNC Identity: Read Impersonated Identity (Fixed Identity): Read
如果您的应用程序使用一个 显式帐户的模拟(也就是说,如果它们模拟一个固定标识),如 <identity impersonate="true" userName="WebUser" password="Y0urStr0ngPassw0rd$"/>£¬那么帐户(在这里是 WebUser)和进程都需要读访问权限。
如果您的基本代码使用通用命名约定 (UNC) 共享,您必须为 IIS 提供的 UNC 标记标识授予读访问权限。
如果您模拟但是没有使用显式凭据,如 <identity impersonate="true"/>£¬而且没有 UNC,那么在 .NET Framework 1.1 中只有进程需要访问权限。对于 .NET Framework 1.0,必须另外配置 ACL,授予任何将被模拟的标识读访问权限(也就是说,您必须授予原始调用方读访问权限)。
ASP.NET 中的信任级
应用程序的信任级决定 CAS 策略授予它何种权限。这决定了多大程度上应用程序能够访问安全资源和执行特权操作。
<trust>
使用 <trust>元素配置应用程序的信任级。默认时,配置级设置为 Full,如下所示:
<!-- level="[Full|High|Medium|Low|Minimal]" --> <trust level="Full" originUrl=""/>
这意味着应用程序将被授予完全和无限的 CAS 权限。使用此配置,应用程序进行的任何资源访问的成败只取决于操作系统安全。
如果您将信任级更改为 Full 之外的其他级,可能破坏现有 ASP.NET Web 应用程序,具体情况取决于它们所访问的资源和它们所执行的操作的类型。应用程序应该彻底地在每个信任级进行测试。
有关构建使用 CAS 的部分信任 Web 应用程序的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。有关使用信任级提供应用程序隔离的更多信息,请参阅“寄宿多个 ASP.NET Web 应用程序”单元。
ASP.NET 的进程标识
ASP.NET Web 应用程序和 Web 服务运行在共享的 ASP.NET 辅助进程 (Aspnet_wp.exe) 实例中。进程级设置,包括进程标识,是使用 Machine.config 中的 <processModel> 元素配置的。
<processModel>
ASP.NET 辅助进程的标识是使用 <processModel> 元素的 userName 和 password 属性配置的。当配置进程标识时,应该:
• |
使用默认 ASPNET 帐户。 |
• |
使用最低特权自定义帐户。 |
• |
加密<processModel>凭据。 |
• |
不以 SYSTEM 帐户运行 ASP.NET。 |
使用默认 ASPNET 帐户
特别对于运行 ASP.NET Web 应用程序和 Web 服务来说,本地 ASPNET 帐户是默认最低特权帐户。如果能够,就通过使用以下默认配置使用此帐户:
<processModel enable="true" userName="machine" password="AutoGenerate" ... />
使用最低特权自定义帐户
如果您必须使用另一个标识运行 ASP.NET 辅助进程,确保所使用的帐户配置为最低特权帐户。这限制了设法使用进程安全上下文执行代码的攻击者所能造成的破坏。
您可能因为需要使用 Windows 身份验证连接远程Microsoft SQL Server_ 数据库或者网络资源,而决定使用另一个帐户。注意您可以将本地 ASPNET 帐户用于此目的。有关更多信息,请参阅本单元后面的“数据访问”。
有关 ASP.NET 进程帐户要求的 NTFS 权限的更多信息,请参阅本单元后面的“ACL 和权限”。
您还应该给 ASP.NET 进程帐户授予以下用户权限:
• |
从网络访问此计算机。 |
• |
登录为批作业。 |
• |
登录为服务。 |
• |
拒绝本地登录。 |
• |
拒绝通过终端服务登录。 |
加密凭据
如果您需要使用自定义帐户,不要在 Machine.config 中存储明文凭据。使用 Aspnet_setreg.exe 实用工具在注册表中存储加密凭据。
加密<processModel> 凭据
1. |
从命令提示运行以下命令: aspnet_setreg -k:Software\YourApp\process -u:CustomAccount :p:StrongPassword 这将在指定的注册表项中存储加密凭据,通过受限 ACL (向 System,、Administrators,和 Creator Owner 授予完全控制权限)保护注册表项。 |
2. |
重新配置 <processModel> 元素并添加以下 userName 和 password 属性。 <processModel userName="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\process\ASPNET_SETREG,password"/> |
有关更多信息,请参阅 Microsoft 知识库文章 329290“如何:使用 ASP.NET 实用工具加密凭据和会话状态连接字符串”。
不以 SYSTEM 运行 ASP.NET
不要使用 SYSTEM 帐户运行 ASP.NET,不要授予 ASP.NET 进程帐户“Act as part of the operating system”用户权限。如果这样做将违反最低特权的原则,能够使用 Web 应用程序的进程安全上下文执行代码的攻击者所带来的破坏将增加。
模拟
默认时,ASP.NET 应用程序并不模拟。在应用程序访问 Windows 资源的时候将使用 ASP.NET 辅助进程帐户(默认时是 ASPNET)的安全上下文。
<identity>
<identity> 元素用于启用模拟。您可以模拟:
• |
原始调用方(经 IIS 身份验证的标识) |
• |
固定标识 |
模拟原始调用方
要模拟原始调用方,使用以下配置:
<identity impersonate="true" />
模拟使用 IIS 提供的表示经身份验证的调用方的访问标记。这可以是匿名 Internet 用户帐户(例如,如果您的应用程序使用窗体身份验证),也可以是表示原始调用方的 Windows 帐户(如果您的应用程序使用 Windows 身份验证)。
如果您确实启用了原始调用方模拟,注意以下问题:
• |
应用程序的可伸缩性降低了,因为数据库连接无法有效地共用。 |
• |
后端资源的 ACL 需要为单独用户配置时,管理工作将增加。 |
• |
委托要求 Kerberos 身份验证和配置合适的 Windows 2000 环境。 |
有关更多信息,请参阅“如何:为 Windows 2000 实现 Kerberos 委托”,在“ Microsoft patterns & practices 第 I 卷,构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”的“如何……”部分,网址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT05.asp。
模拟固定标识
要模拟固定标识,使用 userName 和 <identity> 元素的密码属性指定标识:
<identity impersonate="true" userName="MyServiceAccount" password="Str0ng!Passw0rd"/>
不要像这样以明文存储凭据。相反,使用 Aspnet_setreg.exe 工具加密凭据并将它们存储在注册表中。
加密<identity>凭据
1. |
从命令提示运行以下命令: aspnet_setreg -k:Software\YourApp\identity -u:CustomAccount :p:StrongPassword 这将在指定的注册表项中存储加密凭据,通过受限 ACL (向 System,、Administrators,和 Creator Owner 授予完全控制权限)保护注册表项。 |
2. |
重新配置 <identity> 元素,并添加以下 userName 和 password 属性。 <identity impersonate="true" userName="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,password"/> |
3. |
使用 Regedt32.exe 在上述注册表项中创建 ACL,赋予对 ASP.NET 进程帐户的读访问权限。 |
有关更多信息,请参阅 Microsoft 知识库文章 329290,“如何:使用 ASP.NET 实用工具加密凭据和会话状态连接字符串”。
Act as Part of the operating system 权限
当您通过指定 userName 和 password 属性模拟固定标识时,ASP.NET 1.0 版进程帐户要求 Windows 2000 上的“Act as part of the operating system”用户权限。因为这实际上将提升 ASP.NET 进程帐户到接近本地 System 帐户的特权级,模拟固定标识在 ASP.NET 1.0 版中是不推荐的。
注 如果您是在 Windows 2000 或者 Windows 2003 Server 上运行 ASP.NET 1.1 版,这种用户权限是不需要的。
NTFS 权限需求
NTFS 权限必须为模拟标识进行适当的配置。有关更多信息,请参阅本单元后面的“ACL 和权限”。
身份验证
<authentication>元素能够配置应用程序使用的身份验证模式。
<authentication>
适当的身份验证模式取决于您的应用程序或者 Web 服务如何设计。默认 Machine.config 设置将应用安全 Windows 身份验证默认值,如下所示。
<!-- authentication Attributes: mode="[Windows|Forms|Passport|None]" --> <authentication mode="Windows" />
窗体身份验证准则
要使用窗体身份验证,设置 <authentication> 元素的 mode="Forms"。接下来,使用 <forms> 子元素配置窗体身份验证。以下片段显示了一个安全的 <forms> 身份验证元素配置:
<authentication mode="Forms"> <forms loginUrl="Restricted\login.aspx" Login page in an SSL protected folder protection="All" Privacy and integrity requireSSL="true" Prevents cookie being sent over http timeout="10" Limited session lifetime name="AppNameCookie" Unique per-application name path="/FormsAuth" and path slidingExpiration="true" > Sliding session lifetime </forms> </authentication>
使用以下推荐实践提高窗体身份验证安全性:
• |
为 Web 站点分区。 |
• |
设置 protection="All"。 |
• |
使用小的 cookie 超时值。 |
• |
考虑使用固定的到期时间。 |
• |
在窗体身份验证中使用 SSL。 |
• |
如果您不使用 SSL,设置 slidingExpiration = "false"。 |
• |
不要在产品服务器上使用<credentials>元素。 |
• |
配置<machineKey>元素。 |
• |
使用唯一的 cookie 名称和路径。 |
为 Web 站点分区
将 Web 站点的公共和受限访问区域分离。将应用程序的登录页和其他页,以及应该只由经过身份验证的用户访问的资源置于与公共访问区域不同的文件夹中。通过在 IIS 上配置以要求 SSL 访问保护受限子文件夹,然后使用 <authorization>元素限制访问并强制登录。例如,以下 Web.config 配置允许任何人访问当前目录(这能够提供公共访问),但是要防止未身份验证的用户访问受限子文件夹。任何这样做的企图都将强制窗体登录。
<system.web> <!-- The virtual directory root folder contains general pages. Unauthenticated users can view them and they do not need to be secured with SSL. --> <authorization> <allow users="*" /> </authorization> </system.web> <!-- The restricted folder is for authenticated and SSL access only. --> <location path="Restricted" > <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location>
更多编程方面的注意事项,如如何在受限和非受限页之间导航,请参阅“构建安全的 ASP.NET Web 页和控件”单元中的“窗体身份验证”。
设置 Protection="All"
这个设置能够确保窗体身份验证 cookie 加密,从而提供私密性和完整性。用于 cookie 加密的密钥和算法是在 <machineKey> 元素上指定的。
加密和完整性检查能够防止 cookie 篡改,虽然如果攻击者设法捕获 cookie 的话,它们并不能降低 cookie 重放攻击的风险。还应该使用 SSL 防止攻击者通过使用网络监视软件捕获 cookie。尽管使用了 SSL,cookies 还是能够通过跨站点脚本 (XSS) 攻击窃取。应用程序必须通过适当地输入验证策略,采取足够防范措施,以降低这种风险。
使用小的 cookie 超时值
使用小的超时值限制会话生存期,并减少 cookie 重放攻击的可能性。
考虑使用固定的到期时间
考虑设置 <forms> 元素的 slidingExpiration="false" 以修改 cookie 到期时间,不要在每次 Web 请求之后重新设置到期时间。如果您不使用 SSL 保护 cookie 的话,这是很重要的。
注 此功能在 .NET Framework 1.1 版中提供。
在窗体身份验证中使用 SSL
使用 SSL 保护凭据和身份验证 cookie。SSL 能够防止攻击者捕获凭据或者用来向应用程序标识您的窗体身份验证 cookie。窃取的身份验证 cookie 是一个窃取的登录。
设置 requireSSL="true"这将设置 cookie 中的 Secure 属性,从而确保 cookie 不会从浏览器通过 HTTP 链路传输到服务器。HTTPS (SSL) 是必需的。
注 这是一个 .NET Framework 1.1 版设置。在 1.0 版上构建的应用程序中,设置 cookie Secure属性是通过显式的编程进行的。有关更多信息和示例代码,请参阅“构建安全的 ASP.NET Web 页和控件”单元。
如果您不使用 SSL,设置 slidingExpiration = "false"
通过将 slidingExpiration 设置为 false,可以将 cookie 超时时间修改为距离 cookie 最初创建时的分钟数。否则,超时将在每次向 Web 服务器请求时更新。如果 cookie 被捕获了,将为攻击者提供所需要的足够时间以经过身份验证的用户标识访问应用程序。
注 此功能在 .NET Framework 1.1 版中提供。
不要在产品服务器上使用元素
在 XML 配置文件中存储用户凭据的能力是为了支持快速开发和有限测试而提供的。不要使用实际的最终用户凭据。最终用户凭据不应该存储在产品服务器上的配置文件中。产品应用程序应该实现自定义用户凭据存储区,例如,在一个 SQL Server 数据库中。
配置 machineKey
<machineKey> 元素定义了用来加密窗体身份验证 cookie 的加密算法。此元素还保留着加密密钥。有关更多信息,请参阅本单元中的“机器密钥”部分。
使用唯一的 cookie 名称和路径
使用唯一的 name 和 path 属性值。通过确保名称的唯一,能够防止在同一个服务器上寄宿多个应用程序时可能出现的问题。
授权
除非用户有显式的访问某个资源的权限,如一个特定的 Web 页、一个资源文件、一个目录等等,配置默认时应该拒绝访问。ASP.NET 提供了两个可配置的网关守卫,可以用来控制对受限资源的访问。这两个网关守卫是:
• |
文件授权。这个网关守卫是通过 ASP.NET FileAuthorizationModule HTTP 模块实现的。 |
• |
URL 授权。这个网关守卫是通过 ASP.NET UrlAuthorizationModule HTTP 模块实现的。 |
文件授权
只有使用 Windows 身份验证和具有以下配置的应用程序,才能够使用这个网关守卫:
<authentication mode="Windows"/>
这个网关守卫在使用 Windows 身份验证和无需模拟的情况下,自动生效。为配置此网关守卫,需要配置文件和文件夹上的 Windows ACL。请注意网关守卫只控制对 IIS 映射到以下ASP.NET ISAPI 扩展的文件类型的访问:Aspnet_isapi.dll。
URL 授权
任何应用程序都能够使用这个网关守卫。它是通过 <authorization> 元素(它控制着哪些用户和哪些用户组应该访问应用程序)来配置的。来自 Machine.config 的默认元素如下所示:
<authorization> <!-- allow/deny Attributes: users="[*|?|name]" * - All users ? - Anonymous users [name] - Named user roles="[name]" --> <allow users="*"/> </authorization>
URL 授权注意事项
使用以下措施有助于成功地配置 URL 授权:
• |
Web.config 中的授权设置通常指当前目录和所有子目录中的所有文件,除非子目录的 <authorization> 元素包含自己的 Web.config。在这种情况下,子目录中的设置将改写父目录设置。 |
• |
URL 授权只适用于 IIS 映射到 ASP.NET ISAPI 扩展的文件类型:Aspnet_isapi.dll。 |
• |
当应用程序使用 Windows 身份验证时,将授权访问 Windows 用户和组帐户的权限。用户名的形式为“authority\WindowsUserName”,而角色名的形式为“authority\WindowsGroupName”,其中 authority 要么是一个域名要么是本地机器名称,这取决于帐户类型。 许多众所周知的帐户都是用“BUILTIN”字符串表示的。例如,本地管理员组称为“BUILTIN\Administrators”。本地用户组称为“BUILTIN\Users”。 注 在 .NET Framework 1.0 版中,authority 和组名称是区分大小写的。组名称必须与 Windows 中出现的组名称完全匹配。 |
• |
当应用程序使用窗体身份验证时,将授权自定义用户和在自定义用户存储区中维护的角色。例如,如果您使用窗体对用户向一个数据库进行身份验证,将授权从数据库检索的角色。 |
• |
您可以使用 <location> 标记将授权设置应用到单独的文件或者目录。下例显示了如何将授权应用到一个特定的文件 (page.aspx): <location path="page.aspx" /> <authorization> <allow users="DomainName\Bob, DomainName\Mary" /> <deny users="*" /> </authorization> </location> |
会话状态
依赖于每个用户会话状态的应用程序可以将会话状态存储在以下位置:
• |
在 ASP.NET 辅助进程中 |
• |
在进程外状态服务中,它能够运行在 Web 服务器上,或者运行在一个远程服务器上 |
• |
在 SQL Server 数据存储区中 |
<sessionState>
相关的位置,与连接详细信息一起,存储在 Machine.config 中的 <sessionState> 元素中。这是默认设置:
<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" stateNetworkTimeout="10" sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI" cookieless="false" timeout="20"/>
注 如果您不使用 Web 服务器上的 ASP.NET 状态服务,使用 MMC 服务管理单元禁用它。
保护 SQL Server 会话状态存储区
如果您使用 SQL Server 会话状态存储区,使用以下推荐实践以辅助会话状态的保护:
• |
对数据库使用 Windows 身份验证 |
• |
加密 sqlConnectionString |
• |
限制数据库中的应用程序登录 |
• |
保护信道 |
有关设置 SQL Server 会话状态存储区数据库的更多信息,请参阅 Microsoft 知识库文章 311209,“How To:Configure ASP.NET for Persistent SQL Server Session State Management”。
对数据库使用 Windows 身份验证
如果使用 mode="SQLServer",应该使用 Windows 身份验证连接状态数据库,而且应该使用最低特权帐户,如重复的本地 ASPNET 帐户。这意味着您可以使用可信的连接,连接字符串中不再有凭据,而且凭据不再通过网络传递给数据库。
加密 sqlConnectionString
使用 Aspnet_setreg.exe 工具加密 sqlConnectionString 属性值。如果您使用SQL 身份验证连接状态数据库,这一点尤其重要,因为凭据在连接字符串中,但是即使您使用 Windows 身份验证,也仍然推荐这样做。
加密 sqlConnectionString
1. |
从命令提示运行以下命令。 aspnet_setreg -k:Software\YourApp\sessionState -c:{your connection string} 这将在指定的注册表项中存储加密连接字符串,通过受限 ACL(向 System,、Administrators,和 Creator Owner 授予完全控制权限)保护注册表项。 |
2. |
重新配置 <sessionState> 元素并添加以下 sqlConnectionString 属性。 <sessionState mode="SQLServer" sqlConnectionString="registry:HKLM\SOFTWARE\YourApp\sessionState\ASPNET_SETREG,sqlConnectionString" /> |
3. |
使用 Regedt32.exe 在上述注册表项中创建 ACL,赋予对 ASP.NET 进程帐户的读访问权限。 |
限制数据库中的应用程序登录
数据库中的应用程序登录应该被限制,使其只能用来访问必要的状态表和 ASP.NET 用来查询数据库的存储过程。
要限制状态数据库中的应用程序登录
1. |
在状态数据库服务器上用同样的名称和运行 ASP.NET 应用程序的帐户所用的坚固密码创建重复本地帐户。 有关使用 ASPNET 帐户访问远程数据库的更多信息,请参阅本单元后面的“数据访问”。 |
2. |
创建本地 Windows 组,例如数据库服务器上的 ASPNETWebApps,并将本地 ASPNET 帐户添加到组。 |
3. |
通过创建新的登录授予 Windows 组访问 SQL Server 的权限。 sp_grantlogin 'MACHINE\ASPNETWebApps' 注 用您的数据库服务器名称代替 MACHINE。 |
4. |
授予 SQL 登录访问 ASPState 数据库的权限。以下 T-SQL 将创建一个称为 WebAppUser 的数据库用户,登录将与其相关联。 USE ASPState GO sp_grantdbaccess 'MACHINE\ASPNETWebApps', 'WebAppUser' |
5. |
创建一个用户定义的数据库角色。 USE ASPState GO sp_addrole 'WebAppUserRole' |
6. |
将数据库用户添加到新的数据库角色。 USE ASPState GO sp_addrolemember 'WebAppUserRole', 'WebAppUser' |
7. |
在数据库中为数据库角色配置权限。为 ASPState 数据库提供的存储过程授予执行权限。 grant execute on CreateTempTables to WebAppUserRole 对 ASPState 数据库提供的所有存储过程重复此命令。使用 SQL Server Enterprise Manager 查看完整的列表。 |
保护信道
要保护 Web 服务器的安全和远程状态存储区之间在网络上传输的敏感会话状态,应该使用 IPSec 或者 SSL 保护到两个服务器的信道。这能够为网络上的会话状态数据提供私密性和完整性。如果使用 SSL,则您必须在数据库服务器上安装服务器证书。有关在 SQL Server 中使用 SSL 的更多信息,请参阅“保护数据库服务器”单元。
保护进程外状态服务
如果您使用 mode=StateServer£¬使用以下推荐实践辅助保护会话状态:
• |
使用最低特权帐户运行状态服务 |
• |
保护信道 |
• |
考虑更改默认端口 |
• |
加密状态连接字符串 |
使用最低特权帐户运行状态服务
状态服务默认时使用 ASPNET 本地最低特权帐户运行。您应该不需要更改这一配置。
保护信道
如果状态服务位于远程服务器上,应该使用 IPSec 以确保用户状态保持私密和未经修改,保护到远程状态存储区的信道。
考虑更改默认端口
ASP.NET 状态服务侦听端口 42424。要避免使用这个默认的、众所周知的端口,您可以通过编辑以下注册表项更改端口:
HKLM\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters
端口号是通过 Port 命名值定义的。如果您更改注册表中的端口号,例如,改为 45678,还必须更改 <sessionState> 元素的连接字符串,如下所示:
stateConnectionString="tcpip=127.0.0.1:45678"
加密 stateConnectionString
加密 stateConnectionString 属性值可以隐藏状态存储区的 IP 地址和端口号。使用 Aspnet_setreg.exe 工具。
加密 stateConnectionString
1. |
从命令提示运行以下命令。 aspnet_setreg -k:Software\YourApp\sessionState -d:{your connection string} 这将在指定的注册表项中存储加密连接字符串,通过受限 ACL(向 System、Administrators 和 Creator Owner 授予完全控制权限)保护注册表项。,, |
2. |
重新配置 <sessionState> 元素并添加以下 stateConnectionString 属性: <sessionState mode="StateServer" sqlConnectionString="registry:HKLM\SOFTWARE\YourApp\sessionState\ASPNET_SETREG,sqlConnectionString" ... /> |
3. |
使用 Regedt32.exe 在上述注册表项中创建 ACL,赋予对 ASP.NET 进程帐户的读访问权限。 |
查看状态
如果您的应用程序使用查看状态,确保它使用消息身份验证码 (MAC) 进行了保护,确保没有在客户端更改。可使用 Machine.config 中的 <pages> 元素为机器上所有应用程序启用或者禁用查看状态和 MAC 保护。
<pages>
默认时,Machine.config 中 <pages> 元素的 enableViewStateMac 属性能够确保查看状态使用 MAC 进行了保护。
<pages buffer="true" enableSessionState="true" enableViewState="true" enableViewStateMac="true" autoEventWireup="true" validateRequest="true"/>
如果您使用查看状态,确保 enableViewStateMac 设置为 true。<machineKey> 元素定义了用来保护查看状态的算法。
机器密钥
<machineKey> 元素是用来指定保护窗体身份验证 cookie 和页级查看状态的加密密钥、验证密钥和算法的。以下代码示例显示了来自 Machine.config 的默认设置:
<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey="AutoGenerate,IsolateApps" validation="SHA1"/>
在配置 <machineKey> 时考虑以下推荐实践:
• |
在多个应用程序中使用唯一加密密钥 |
• |
设置 validation="SHA1" |
• |
为 Web 服务器场手工生成密钥 |
在多个应用程序中使用唯一加密密钥
如果您在一个 Web 服务器上寄宿多个应用程序,机器上的每个应用程序都使用唯一密钥,而不是对所有应用程序都使用一个密钥。这消除了一个应用程序能够欺骗寄宿环境中查看状态或者已加密窗体身份验证 cookie 的可能性。
还需要使用 IsolateApps 设置。这是一个新的 .NET Framework 1.1 版设置,指示 ASP.NET 自动生成加密密钥,使每个应用程序都有唯一的密钥。
设置 validation="SHA1"
validation 属性指定了用于完整性检查和页级查看状态的算法。可能的值是“SHA1,”、“MD5,”和“3DES”。
如果您使用 <forms> 元素上的 protection="All",则窗体身份验证 cookie 将加密,这也能确保完整性。无论 validation 属性设置如何,窗体身份验证使用 TripleDES (3DES) 加密 cookie。
注 窗体身份验证 cookie 加密与 validationkey 设置无关,而且密钥是以 decryptionKey 属性为基础的。
如果您设置 <machineKey> 上的 validation="SHA1",则应该使用 SHA1 算法对页级查看状态进行完整性检查,假定 <pages> 元素为查看状态 MAC 进行了配置。有关更多信息,请参阅本单元前面的“查看状态”。
您还可以设置验证属性为 MD5。您应该使用 SHA1,因为它能够生成比 MD5 更大的散列,所以可以认为更加安全。
如果您设置 <machineKey> 的 validation="3DES" £¬然后使用 3DES 算法加密页级查看状态(还提供完整性检查),即使 <pages> 元素为查看状态 MAC 进行了配置。
为 Web 服务器场手工生成密钥
在 Web 服务器场中,必须设置显式密钥值,且 Web 服务器场中所有机器都使用同样的密码。请参阅本单元后面的“Web 服务器场注意事项”。
调试
<compilation> 元素控制着用于动态页编译的编译器设置,这是在客户端请求 Web 页(.aspx 文件)或者 Web 服务(.asmx 文件)时启动的。不要在产品服务器上使用调试版本,这一点很重要,因为调试信息对于攻击者很有价值,可能暴露源代码详细信息。
<compilation>
此元素控制着编译进程。确保产品服务器上禁用调试编译。如下设置 debug="false":
<compilation debug="false" explicit="true" defaultLanguage="vb" />
默认时,临时文件在以下目录创建和编译:
%winnt%\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files
您可以使用 tempDirectory 属性指定每个应用程序的位置,虽然这不能提供安全优势。
注 <processModel> 元素指定的 ASP.NET 进程标识要求临时编译目录的完全控制访问权限。
千万不要将调试文件(带有 .pdb 扩展名)存储在程序集所在的产品服务器上。
跟踪
跟踪不应该在产品服务器上启用,因为系统级跟踪信息能够极大地帮助攻击者分析应用程序和探查弱点。
<trace>
跟踪是使用 <trace> 元素配置的。在产品服务器上设置 enabled="false",如下所示:
<trace enabled="false" localOnly="true" pageOutput="false" requestLimit="10" traceMode="SortByTime"/>
如果您确实需要跟踪活动应用程序的问题,在测试环境中模拟问题更好,或者如果必要,可以启用跟踪并设置 localOnly="true",以防止跟踪详细信息返回远程客户端。
异常管理
不要允许异常详细信息从您的 Web 应用程序传播回客户端。恶意用户可能使用系统级诊断信息了解您的应用程序,并探查弱点,供未来攻击中利用。
<customErrors>
<customErrors> 元素可以用来配置自定义的、一般性错误消息,这类消息将在应用程序出现异常情形时返回客户端。错误页应该包括一个合适的一般性错误消息,还有可选的更多支持详细信息。您还可以使用此元素根据异常情形返回不同的错误页。
确保模式属性设置为 "On",而且已经指定了默认的重定向页,如下所示:
<customErrors mode="On" defaultRedirect="YourErrorPage.htm" />
defaultRedirect 属性使您能够在应用程序中使用自定义错误页,例如可以包括支持联系人详细信息。
注:不要使用 mode="Off",因为它会导致包含系统级信息的详细的错误页被返回给客户端。
如果您想不同类型的错误有不同的错误页,使用一个或者更多 <error> 元素,如下所示。在此例中,“404 (not found)”错误重定向到一个页,“500 (internal system errors)”重定向到另一页,而所有其他错误都定向到 defaultRedirect 属性指定的页。
<customErrors mode="On" defaultRedirect="YourErrorPage.htm"> <error statusCode="404" redirect="YourNotFoundPage.htm"/> <error statusCode="500" redirect="YourInternalErrorPage.htm"/> </customErrors>
远程处理
不要公开面向 Internet 的 Web 服务器上的 .NET 远程处理终结点。要禁用远程处理,需要通过将这些文件扩展名的请求映射到 HttpForbiddenHandler 禁用 .rem 和 .soap 扩展名的请求。使用 <httpHandlers> 下的以下元素:
<httpHandlers> <add verb="*" path="*.rem" type="System.Web.HttpForbiddenHandler"/> <add verb="*" path="*.soap" type="System.Web.HttpForbiddenHandler"/> . . . </httpHandlers>
注 这不能防止 Web 服务器上的 Web 应用程序通过使用远程处理基础结构连接下游对象。但是,它可防止客户端能够连接 Web 服务器上的对象。
Web 服务
使用 <webServices> 元素配置 Web 服务。要建立安全的 Web 服务配置:
• |
如果 Web 服务不是必需的就将其禁用 |
• |
禁用未用的协议 |
• |
禁用 WSDL 的自动生成 |
如果 Web 服务不是必需的就将其禁用
如果您不使用 Web 服务,通过将 .asmx(Web 服务)文件扩展名的请求映射到 Machine.config 中的 HttpForbiddenHandler 禁用它们,如下所示:
<httpHandlers> <add verb="*" path="*.asmx" type="System.Web.HttpForbiddenHandler"/> . . . </httpHandlers>
禁用未用的协议
<protocols> 元素定义了 Web 服务支持的协议。默认时,HttpPost 和 HttpGet 在 .NET Framework 1.1 版上禁用,如下所示:
<webServices> <protocols> <add name="HttpSoap1.2"/> <add name="HttpSoap"/> <!-- <add name="HttpPost"/> --> <!-- <add name="HttpGet"/> --> <add name="HttpPostLocalhost"/> <add name="Documentation"/> </protocols> </webServices>
通过禁用不必要的协议,包括 HttpPost 和 HttpGet£¬可以减少受攻击面。例如,外部攻击者可能通过在电子邮件中嵌入一个恶意的链接,从而使用最终用户的安全上下文执行内部 Web 服务。禁用 HttpGet 协议是一种有效的对策。在许多方面,这与 XSS 攻击是类似的。这种攻击的变体是使用一个 <img src="..." /> 标记在能够公开访问的 Web 页中嵌入对 intranet Web 服务的 GET调用。这两种攻击都允许外人调用内部的 Web 服务。禁用协议可以降低风险。
如果您的产品服务器提供了可以公开发现的 Web 服务,则必须启用 HttpGet 和 HttpPost 以允许服务通过这些协议被发现。
禁用 WSDL 的自动生成
文档协议是用来动态生成 Web 服务描述语言 (WSDL) 的。WSDL 说明了一个 Web 服务的特性,如它的方法签名和所支持的协议。客户端使用这种信息适当地构造格式化的消息。默认时,Web 服务公开 WSDL,这能够使它为任何能够通过 Internet 连接 Web 服务器的人所访问。
有时候,您可能需要手工将 WSDL 文件分发给您的合作伙伴并防止公开访问。通过这种方式,开发小组能够提供每个 Web 服务的单独 .wsdl 文件给操作小组。操作小组然后能够将它们分发给想使用这些 Web 服务的指定合作伙伴。
要禁用文档协议,在 Machine.config 中将其注释掉,如下所示:
<webServices> <protocols> <add name="HttpSoap"/> <!-- <add name="Documentation"/> --> </protocols> </webServices>
禁止的资源
为了防止受保护的资源和文件通过 HTTP 下载,将它们映射到 ASP.NET HttpForbiddenHandler.
将受保护资源映射到 HttpForbiddenHandler
HTTP 处理程序位于 <httpHandlers> 元素之下的 Machine.config 中,。HTTP 处理程序负责处理特定文件扩展名的 Web 请求。远程处理不应该在前端 Web 服务器上启用;只应该在与 Internet 隔离的中间层应用程序服务器上启用远程处理。
• |
以下文件扩展名在 Machine.config 中映射到相应的 HTTP 处理程序: |
• |
.aspx 用于 ASP.NET 页。 |
• |
.rem 和 .soap 用于远程处理。 |
• |
.asmx 用于 Web 服务。 |
• |
.asax、.ascx、.config、.cs、.csproj、.vb、.vbproj、.webinfo、.asp、.licx、.resx 和 .resources 都是受保护资源,都可被映射到 System.Web.HttpForbiddenHandler. |
对于 .NET Framework 资源,如果您不使用文件扩展名,那么应该将扩展名映射到 Machine.config 中的 System.Web.HttpForbiddenHandler£¬如下例所示:
<add verb="*" path="*.vbproj" type="System.Web.HttpForbiddenHandler" />
在这种情况下,.vbproj 文件扩展名映射到 System.Web.HttpForbiddenHandler如果客户端请求的路径以 .vbproj 结束,那么 ASP.NET 将返回一条消息,说明“This type of page is not served”。
• |
以下准则适用于处理 .NET Framework 文件扩展名: |
• |
将不使用的扩展名映射到 HttpForbiddenHandler.如果您不支持 ASP.NET 页,那么就将 .aspx 映射到 HttpForbiddenHandler.如果您不使用 Web 服务,那么就将 .asmx映射到 HttpForbiddenHandler. |
• |
在面向 Internet 的 Web 服务器上禁用远程处理。将在面向 Internet 的 Web 服务器上的远程处理扩展名(.soap 和 .rem)映射到 HttpForbiddenHandler. |
Bin 目录
ASP.NET 应用程序的虚拟根目录下的 Bin 目录包含应用程序的私有程序集,如果在开发期间使用了代码隐藏文件的话,还包括应用程序的页类实现。
保护 Bin 目录
要保护应用程序的 Bin 目录,并保护您的业务逻辑免遭无意的下载:
• |
删除 Web 权限。 |
• |
删除所有身份验证设置。 |
删除 Web 权限
使用 IIS 管理单元,确保 Bin 目录没有 Read£¬、Write£¬或者 Directory 浏览权限。还要确保 Execute 权限设置为 None.
删除所有身份验证设置
使用 IIS 管理单元从 Bin 目录删除身份验证设置。这将导致所有访问被拒绝。
事件日志
最低特权帐户,如 ASPNET,有足够权限,能够使用现有事件源向事件日志中写入记录。但是,它们没有足够权限创建新的事件源。要实现这一点,您必须在以下注册表项下放置新的项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\
要避免这一问题,您可以在安装时有管理员特权时创建事件源。您可以使用 .NET 安装程序类,它可以由 Windows 安装程序(如果您使用 .msi 部署)或者由 InstallUtil.exe 系统实用工具(如果您没有使用 .msi 部署)实例化。有关使用事件日志安装程序的更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元。
如果您不能在安装时创建事件源,必须在以下注册表项中添加权限,并授予 ASP.NET 进程帐户或者任何模拟帐户(如果您的应用程序使用模拟)访问权限。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
最低限度,这类帐户必须有以下权限:
• |
查询项值 |
• |
设置项值 |
• |
创建子项 |
• |
枚举子项 |
• |
通知 |
• |
读取 |
文件访问
应用程序所访问的任何文件的 ACL 中,必须有一个访问控制项 (ACE) 至少授予 ASP.NET 进程帐户或者模拟标识读访问权限。通常,ACL 在目录上配置,文件将继承设置。
除了使用 NTFS 权限限制文件和目录访问外,您还可以使用 ASP.NET 信任级对 Web 应用程序和 Web 服务实施约束,以限制它们能够访问文件系统的哪些区域。例如,中度信任的 Web 应用程序只能访问它们自己虚拟目录层次中的文件。
有关 ASP.NET CAS 策略的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。
ACL 和权限
ASP.NET 进程帐户,对于一些目录而言,还包括任何模拟标识(如果您的应用程序使用模拟的话)要求以下 NTFS 权限。表 3 中列出了除了应用程序访问特定于应用程序的文件系统资源所需的任何权限之外,还应该使用的权限。
表 3 ASP.NET 进程帐户必需的 NTFS 权限 | |
目录 | 必需权限 |
临时 ASP.NET 文件 |
进程帐户和模拟标识:完全控制 |
临时目录 |
进程帐户: |
.NET Framework 目录 |
进程帐户和模拟标识: |
.NET Framework 配置目录 |
进程帐户和模拟标识: |
Web 站点根目录 |
进程帐户: |
系统根目录 |
进程帐户: |
全局程序集缓存 |
进程帐户和模拟标识:读 |
内容目录 |
Process account: Read and Execute List Folder Contents Read Note: With .NET Framework version 1.0, all parent directories, back up to the file system root directory, also require the above permissions. Parent directories include: C:\ C:\inetpub\ C:\inetpub\wwwroot\ |
注册表
应用程序访问的任何注册表项的 ACL 中,必须有一个 ACE 至少授予 ASP.NET 进程帐户或者模拟标识读访问权限。
数据访问
为了从 ASP.NET 应用程序使用 Windows 身份验证访问远程数据库,有以下选择:
• |
使用默认 ASP.NET 进程帐户。通过用数据库服务器上同样的用户名和密码创建镜像帐户,以使用默认 ASP.NET 进程帐户。在 Windows 2000 上,默认进程帐户是 ASPNET。在 Windows Server 2003 上,默认进程帐户是 NetworkService。 使用本地帐户的缺点在于,如果您能够转储 SAM 数据库的话(这需要管理特权),那么您就可以访问凭据。而主要的优点是,本地帐户能够限制在特定的服务器上,使用域帐户很难做到这一点。 |
• |
使用最低特权域帐户运行 ASP.NET。这种方法简化了管理,而且这意味着您不需要同步镜像帐户的密码。如果 Web 服务器和数据库服务器处在不同的不可信域,或者有一个防火墙分隔了两个服务器,而防火墙不允许 Windows 身份验证必要的端口,这种方法都无法实现。 |
• |
模拟匿名 Web 帐户。 如果您使用窗体或者 Passport 身份验证,可以模拟匿名 Web 帐户(默认时是 IUSR_MACHINE),在数据库服务器上创建镜像帐户。此方法在同一个 Web 服务器中寄宿多个 Web 应用程序的场景中非常有用。您可以使用 IIS,用不同的匿名帐户配置每个应用程序的虚拟目录。 在 Windows Server 2003 上,您可以在不同的辅助进程中运行多个应用程序,使用 IIS 6.0 应用程序池,为每个应用程序配置不同的标识。 |
为 ASP.NET 应用程序配置数据访问
无论使用何种方法,都应该限制数据库中应用程序的帐户。要实现这一点,为帐户创建一个 SQL Server 登录,授予它访问必需的数据库的权限,并限制其权限,从而使其只能访问最少的必需数据库对象。理想情况下,您应该限制权限从而使登录只能访问应用程序或者 Web 服务使用的存储过程。
以下过程假设您使用一个镜像本地帐户,但是也可以通过一个域帐户使用同样的方法限制数据库中帐户的功能。
为 ASP.NET 应用程序配置数据库访问
1. |
使用计算机管理工具将 Web 服务器上本地 ASPNET 帐户的密码更改为已知的坚固密码。 您需要实现这一点,从而能够在数据库服务器上创建一个镜像帐户。 |
2. |
更改 Machine.config 中 <processModel> 元素的 password 属性,使 ASP.NET 辅助进程能够继续使用 ASPNET 帐户运行。使用 spnet_setreg.exe 在注册表中存储加密凭据。 |
3. |
使用数据库服务器上相同的名称 (ASPNET) 和坚固的密码在数据库服务器上创建本地帐户。 |
4. |
在数据库服务器上创建本地 Windows 组,如 ASPNETWebApp,然后在组中添加本地 ASPNET 帐户。 |
5. |
通过创建新的登录授予 Windows 组访问 SQL Server 的权限,如下所示: sp_grantlogin 'MACHINE\ASPNETWebApp' 注 用您的数据库服务器名称代替 MACHINE。 |
6. |
授予 SQL 登录访问数据库的权限。以下 T-SQL 创建了一个称为 WebAppUser 的数据库用户,登录与此用户相关联。 USE YourDatabase GO sp_grantdbaccess 'MACHINE\ASPNETWebApp', 'WebAppUser' |
7. |
创建一个用户定义的数据库角色。 USE YourDatabase GO sp_addrole 'WebAppUserRole' |
8. |
向新的数据库角色中添加数据库用户。 USE YourDatabase GO sp_addrolemember 'WebAppUserRole', 'WebAppUser' |
9. |
在数据库中为数据库角色配置权限。理想情况下,只为这样的存储过程授予执行权限:应用程序用这种存储过程来查询数据库而且不提供直接表访问。 grant execute on sprocname to WebAppUserRole |
UNC 共享
ASP.NET 应用程序可以使用 UNC 共享的两个主要方式是:
• |
访问 UNC 共享上的文件 例如,应用程序必须访问一个远程文件,如 \\remoteserver\share\somefile.dat。 |
• |
在 UNC 共享上寄宿应用程序 应用程序的 IIS 虚拟目录映射到一个远程共享,例如,\\remoteserver\appname。在此场景中,由 Web 服务器处理 HTTP 请求,但是应用程序的页、资源和私有程序集位于远程共享。 |
访问 UNC 共享上的文件
如果您的应用程序访问 UNC 共享上的文件,ASP.NET 进程帐户或者任何模拟标识必须有适当的访问权限(由共享上和基础目录或者文件上的 ACL 所定义)。
如果您使用本地 ASPNET 进程帐户,则没有网络标识,因此必须使用一个匹配的用户名和密码在远程服务器上创建一个镜像帐户,或者您必须使用有两个服务器访问权限的最低特权域帐户。在 Windows Server 2003 上,用来运行 ASP.NET Web 应用程序的 NetworkService 帐户可以在网络上进行身份验证,因此所有要做的就是授予机器帐户访问权限。
在 UNC 共享上寄宿应用程序
您可以使用 IIS 配置虚拟目录指向位于另一个计算机上的 UNC 共享,例如 \\remoteserver\appname。当这样做的话,IIS 将提示您提供帐户凭据,使用这一凭据建立与远程计算机的连接。
注 帐户凭据以加密格式存储在 IIS 元数据库中,但是能够通过 API 访问。您应该确保使用最低特权帐户。有关更多信息,请参阅 Microsoft 知识库文章 280383,“IIS Security Recommendations When You Use a UNC Share and UserName and Password Credentials”。
如果您的应用程序位于一个 UNC 共享上,ASP.NET 模拟 IIS 提供的 UNC 标记(从您提供给 IIS 的帐户凭据创建)来访问共享,除非您已经启用模拟,使用一个固定模拟标识,如以下配置所示:
<identity impersonate="true" userName="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\identity\ASPNET_SETREG,password"/>
如果通过 userName 和 password 属性提供一个固定模拟帐户,ASP.NET 应该使用该帐户而不是 IIS UNC 标记来访问共享。应用程序所进行的任何资源访问也使用固定模拟帐户。
注 上例中,Aspnet_setreg.exe 用来在注册表中存储加密帐户凭据。
如果您通过使用以下配置启用对原始调用方(经 IIS 身份验证的标识)的模拟,ASP.NET 仍然使用 UNC 提供的标记访问共享中应用程序的文件,虽然应用程序进行的任何资源访问都使用模拟标记。
<identity impersonate="true" />
注 用于 UNC 共享的帐户必须还能够读取 Machine.config。
代码访问安全注意事项
代码访问安全策略授予 UNC 共享上的应用程序 intranet 权限集。intranet 权限集不包含 AspNetHostingPermission£¬而这是 ASP.NET Web 应用程序运行所要求的,因此应用程序如果不显式修改策略就无法运行。
这时您有两种选择:
• |
将完全信任授予寄宿应用程序的 UNC 共享。 这是最容易管理的选择,而且如果您运行 .NET Framework 1.0 版,这是唯一的选择,因为 ASP.NET 1.0 版的 Web 应用程序需要完全信任。 |
• |
配置代码访问安全策略授予代码 AspNetHostingPermission£¬并根据访问的资源类型和执行的操作授予可能需要的任何其他权限。 因为 ASP.NET 动态创建代码和编译页类的方式,在配置策略时您必须为 UNC 和临时 ASP.NET 文件目录使用代码组。默认的临时目录是 \WINNT\Microsoft.NET\Framework\{version}\Temporary ASP.NET Files,但此位置可以通过使用 <compilation> 元素的 tempDirectory 属性对每个应用程序进行配置。 有关 ASP.NET 代码访问安全策略和用沙箱保护特权代码的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。 注 配置策略时,您应该给共享(通过使用文件位置)而不是给区域授予信任。这能够提供更细的粒度,因为您不会影响特定区域中的所有应用程序。 |
COM/DCOM 资源
应用程序在调用基于 COM 的资源如服务组件时,需要使用进程或者模拟标识。客户端身份验证和模拟级是使用 Machine.config 中 <processModel> 元素的 comAuthenticationLevel 和 comImpersonation 级别属性配置的。
有关更多信息和推荐实践,请参阅“保护应用程序服务器的安全”单元中的“企业服务注意事项”。
拒绝服务注意事项
ASP.NET 具有以下功能,有助于对抗以 ASP.NET 应用程序为目标的拒绝服务攻击:
• |
POST 请求默认时限制为 4 兆字节 (MB)。 |
• |
检查客户端以确保它们在请求排队等候之前仍然连接。这在攻击者发送多个请求然后断开它们的情况下会出现。 |
• |
请求执行在可配置限制之后超时。 |
<httpRuntime>
配置值在 Machine.config 的 <httpRuntime> 元素中维护。以下代码示例显示了来自 1.1 版 Machine.config 的默认设置:
<httpRuntime executionTimeout="90" maxRequestLength="4096" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100" enableVersionHeader="true"/>
可能需要减少 maxRequestLength 属性的值以防止用户上传非常大的文件。最大允许值是 4 MB。在 Open Hack 竞赛中,maxRequestLength 约束为 1/2 MB,如在下例所示:
<system.web> <!-- 1/2 MB Max POST length --> <httpRuntime maxRequestLength="512"/> </system.web>
注 ASP.NET 不能应对数据包级攻击。您必须通过加固 TCP/IP 堆栈解决这一问题。有关配置 TCP/IP 堆栈的更多信息,请参阅本指南的“如何……”部分中的“如何加固 TCP/IP 堆栈”。
Web 服务器场注意事项
如果您的 ASP.NET Web 应用程序运行在 Web 服务器场中,将无法保证来自同一客户端的后续请求会由同一台 Web服务器服务。这对以下方面都有影响:
• |
会话状态 |
• |
加密和验证 |
• |
DPAPI |
会话状态
要避免服务器关系,应该在 ASP.NET SQL Server 状态数据库中维护进程外 ASP.NET 会话状态,或者在运行在远程机器上的进程外状态服务中维护它。有关在远程状态存储区中保护会话状态的更多信息,请参阅本文档前面的“会话状态”部分。
加密和验证
用来加密和验证窗体身份验证 cookie和查看状态的密钥,在 Web 服务器场中所有服务器必须是一样的。<machineKey> 元素的 AutoGenerate 设置必须用公共的密钥值代替。
有关生成和配置密钥的更多信息,请参阅 Microsoft 知识库文章 312906,“How To:Create Keys by Using Visual C# .NET for Use in Forms Authentication”。
DPAPI
为了加密数据,开发人员有时会使用 DPAPI。如果您使用带机器密钥的 DPAPI 存储机密,则已加密的字符串是特定于给定计算机的,不能在 Web 服务器场或者群集中的计算机复制已加密数据。
如果您使用带用户密钥的 DPAPI,可以解密任何带有漫游用户配置文件的计算机上的数据。但是,因为数据可以被网络上任何能够使用加密数据的帐户执行代码的机器解密,这种做法是不推荐的。
DPAPI 理想情况下适合用于存储配置机密,例如,Web 服务器上的数据库连接字符串。在已加密数据存储在远程服务器例如在数据库中时,应该使用其他加密技术。有关在数据库中存储加密数据的更多信息,请参阅“构建安全的数据访问”单元。
安全 ASP.NET 应用程序的快照
以下快照显示了安全 ASP.NET 应用程序的属性,可以用来快速和容易地将此设置与您自己的配置进行比较。
表 4:安全 ASP.NET 应用程序配置的快照 | |
组件 | 特性 |
进程标识 |
以 ASPNET 帐户运行的 ASP.NET 辅助进程: <processModel username="machine" password="AutoGenerate" /> 自定义帐户(如果使用了)是最低特权。 <processModel userName="registry:HKLM\SOFTWARE\YourApp\ process\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\ process\ASPNET_SETREG,password"/> |
模拟 |
模拟标识是在注册表中加密的: <identity impersonate="true" userName="registry:HKLM\SOFTWARE\YourApp\ identity\ASPNET_SETREG,userName" password="registry:HKLM\SOFTWARE\YourApp\ identity\ASPNET_SETREG,password"/> |
身份验证 |
Web 站点是按公共访问和受限访问划分的。 窗体身份验证配置是安全的: <forms loginUrl="Restricted\login.aspx" protection="All" requireSSL="true" timeout="10" name="AppNameCookie" path="/FormsAuth" slidingExpiration="true" /> 对身份验证 cookie 进行了加密和完整性检查。 |
授权 |
ACL 是在 ASP.NET 资源上进行配置的。将配置 |
会话状态 |
如果不需要,禁用 ASP.NET 状态服务。 <sessionState mode="Off " /> 如果必要,加密与远程状态存储区的通信信道。 |
查看状态 |
启用 Machine.config 中 <pages>元素的查看状态 MAC。 |
机器密钥 |
validation 属性设置为 SHA1。 ViewState 和窗体身份验证是受保护的: <machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey="AutoGenerate,IsolateApps" validation="SHA1"/> |
禁止 |
受保护资源映射到 System.Web.HttpForbiddenHandler。 |
调试 |
禁用调试版本: <compilation debug="false" . . . |
跟踪 |
禁用跟踪。 <trace enabled='false' localOnly='true . . . |
异常管理 |
启用自定义错误。 <customErrors mode="On" defaultRedirect="YourErrorPage.htm" /> |
远程处理 |
在面向 Internet 的 Web 服务器上远程处理是禁用的: <httpHandlers> <add verb="*" path="*.soap" type="System.Web.HttpForbiddenHandler"/> <add verb="*" path="*.rem" type="System.Web.HttpForbiddenHandler"/> . . . </httpHandlers> |
Web 服务 |
如果不是必需的话,Web 服务是禁用的: <httpHandlers> <add verb="*" path="*.asmx" type="System.Web.HttpForbiddenHandler"/> . . . </httpHandlers> 禁用不必要的协议: <webServices> <protocols> <!-- <add name="HttpPost"/> --> <!-- <add name="HttpGet"/> 禁用文档协议以防止自动生成 WSDL: <webServices> <protocols> <!--<add name="Documentation"/>-->. . . |
Bin 目录 |
Bin 目录是受保护的。 |
小结
本单元通过将注意力集中在一些配置类别(包括在 Machine.config 和 Web.config 文件中维护的帐户、服务、协议、文件和目录和配置数据)上,说明了如何保护 ASP.NET Web 应用程序或者 Web 服务的安全。本单元还说明了如何保护 ASP.NET Web 应用程序的安全和 Web 服务所依赖的各种功能区域,包括身份验证、授权、会话状态和数据访问。
有关相关的核对表,请参阅“核对表:保护 ASP.NET 的安全”。
其他资源
有关更多信息,请参阅以下资源和文章:
• |
您可以下载针对 Microsoft .NET 的 Web Services Enhancements (WSE) 1.0 SP1,网址是:http://microsoft.com/downloads/details.aspx?FamilyId=06255A94-2635-4D29-A90C-28B282993A41&displaylang=en。 |
• |
Microsoft 知识库文章 329290,“如何:使用 ASP.NET 实用工具加密凭据和会话状态连接字符串”。 |
• |
Microsoft 知识库文章 311209,“How To:Configure ASP.NET for PersistentSQLServerSessionState Management”。 |
• |
Microsoft 知识库文章 312906,“如何:Create Keys by Using Visual C# .NET for Use in Forms Authentication”。 |
• |
“如何:为 Windows 2000 实现 Kerberos 委托”,在“Microsoft patterns & practices 第 I 卷,构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”的“如何……”部分中,网址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT05.asp。 |
• |
有关从 Open Hack 竞赛得出的安全注意事项的更多信息,请参阅 MSDN 文章“Building and Configuring More Secure Web Sites”,网址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/openhack.asp。 |