在进程外状态服务(可以在 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 来确保注册表项的安全,该 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.
授予对 ASPState 数据库的 SQL 登录访问权限。下面的 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 企业管理器查看完整列表。
确保通道安全
要保护通过网络在 Web 服务器和远程状态存储之间传输的敏感会话状态,应使用 IPSec 或 SSL 确保到两个服务器的通道的安全。这为整个网络间的会话状态数据提供了私密性和完整性。如果使用 SSL,必须在数据库服务器上安装服务器证书。有关在 SQL Server 上使用 SSL 的详细信息,请参阅模块 18 保证数据库服务器的安全。
确保进程外状态服务的安全
如果使用 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:{连接字符串}
此命令会将加密的连接字符串存储在指定的注册表项中,并通过受限制的 ACL 来确保注册表项的安全,该 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。有关详细信息,请参阅本模块前面的视图状态。
也可以将 validation 属性设置为 MD5。应该使用 SHA1,因为此算法生成的哈希值比 MD5 要大,因此更安全。
如果在 <machineKey> 上设置了 validation="3DES",将使用 3DES 算法为页面级视图状态加密(同时还检查完整性),即使 <pages> 元素配置为视图状态 MAC。
手动为 Web 场生成密钥
在 Web 场中,必须设置明确的密钥值,并在 Web 场中的所有计算机上使用相同的密钥值。请参阅本模块后面的 Web 场注意事项。
调试
<compilation> 元素控制用于动态页面编译的编译器设置,该编译器在客户端请求网页(.aspx 文件)或 Web Services(.asmx 文件)时启动。不要在生产服务器上使用调试内部版本,这一点非常重要,因为攻击者可能会利用调试信息,并且可能会泄漏源代码的详细信息。
<compilation>
此元素控制编译进程。请确保在生产服务器上禁用调试编译。设置 debug="false",如下所示:
<compilation debug="false" explicit="true" defaultLanguage="vb" />
默认情况下,将在以下目录中创建和编译临时文件:
%winnt%\Microsoft.NET\Framework\{版本}\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> 元素可用于配置自定义的一般错误消息,在应用程序发生异常时应将该消息返回到客户端。错误页面应包括相应的一般错误消息,并且可以包含额外的支持详细信息。使用此元素还可以根据异常情况返回不同的错误页面。
请确保将 mode 属性设置为 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 远程处理终结点。要禁用远程处理,可通过将对 .rem 和 .soap 文件扩展名的请求映射到 HttpForbiddenHandler,以禁用对这些扩展名的请求。在 <httpHandlers> 下使用以下元素:
<httpHandlers>
<add verb="*" path="*.rem" type="System.Web.HttpForbiddenHandler"/>
<add verb="*" path="*.soap" type="System.Web.HttpForbiddenHandler"/>
. . .
</httpHandlers>
注意 这不会阻止 Web 服务器上的 Web 应用程序使用远程处理基础结构连接下游对象。不过,它会阻止客户端连接到 Web 服务器上的对象。
Web Services
可以使用 <webServices> 元素配置 Web Services。建立安全的 Web Services 配置:
•
禁用不需要的 Web Services
•
禁用不使用的协议
•
禁止自动生成 WSDL
禁用不需要的 Web Services
如果不使用 Web Services,可通过将对 .asmx(Web Services)文件扩展名的请求映射到 Machine.config 中的 HttpForbiddenHandler 来禁用 Web Services,如下所示:
<httpHandlers>
<add verb="*" path="*.asmx" type="System.Web.HttpForbiddenHandler"/>
. . .
</httpHandlers>
禁用不使用的协议
<protocols> 元素可以定义 Web Services 支持的协议。默认情况下,.NET Framework 1.1 上禁用 HttpPost 和 HttpGet,如下所示:
<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 Services。禁用 HttpGet 协议是一个有效的对策。这在许多方面与 XSS 攻击类似。此攻击的不同之处在于,它在公共访问网页上使用 <img src="..."/> 标记将 GET 调用嵌入 Intranet Web Services 中。这两种攻击都允许外部用户调用内部 Web Services。禁用协议可以降低风险。
如果生产服务器提供可以公共搜索的 Web Services,则必须启用 HttpGet 和 HttpPost,以便可以通过这些协议搜索该服务。
禁止自动生成 WSDL
文档协议用于动态生成 Web Services 描述语言 (WSDL)。WSDL 描述 Web Services 的特性,如该服务的方法签名和所支持的协议。客户端使用这些信息构建相应格式的消息。默认情况下,Web Services 会公开 WSDL,允许任何可以通过 Internet 连接到 Web 服务器的用户使用。
有时,可能需要手动将 WSDL 文件分发给合作伙伴,以禁止公共访问。通过这种方法,开发小组可以分别将每个 Web Services 的 .wsdl 文件分发给业务组。然后,由业务组将其分发给需要使用 Web Services 的指定合作伙伴。
要禁用文档协议,应在 Machine.config 中注释掉该协议,如下所示:
<webServices>
<protocols>
<add name="HttpSoap"/>
<!-- <add name="Documentation"/> -->
</protocols>
</webServices>
禁止访问的资源
要禁止通过 HTTP 下载受保护的资源和文件,请将这些资源和文件映射到 ASP.NET 的 HttpForbiddenHandler。
将受保护的资源映射到 HttpForbiddenHandler
HTTP 处理程序位于 Machine.config 中的 <httpHandlers> 元素下。HTTP 处理程序负责处理对特定文件扩展名的 Web 请求。不应在前端 Web 服务器上启用远程处理;只应在与 Internet 隔离的中间层应用程序服务器上启用远程处理。
•
以下文件扩展名在 Machine.config 中映射到 HTTP 处理程序:
•
.aspx 用于 ASP.NET 页面。
•
.rem 和 .soap 用于远程处理。
•
.asmx 用于 Web Services。
•
.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 Services,则将 map .asmx 映射到 HttpForbiddenHandler。
•
在访问 Internet 的 Web 服务器上禁用远程处理。将访问 Internet 的 Web 服务器上的远程处理扩展名(.soap 和 .rem)映射到 HttpForbiddenHandler。
bin 目录
ASP.NET 应用程序虚拟根目录下的 bin 目录包含应用程序的专用程序集,如果在开发过程中使用了代码隐藏文件,则包括应用程序的页面级实现。
确保 bin 目录的安全
确保应用程序的 bin 目录的安全,并防止无意中下载业务逻辑:
•
删除 Web 权限。
•
删除所有身份验证设置。
删除 Web 权限
使用 IIS 管理单元来确保 bin 目录没有读取、写入或目录浏览权限。还要确保将“执行”权限设置为“无”。
删除所有身份验证设置
使用 IIS 管理单元从 bin 目录中删除身份验证设置。这会造成所有访问均被拒绝。
事件日志
最小特权帐户(如 ASPNET)具有充分的权限,可以使用现有的事件来源在事件日志中写入记录。但是,其权限不足以创建新的事件来源。要创建新的事件来源,必须在以下注册表项下加入一个新条目:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\<log>
为了避免这个问题,如果具有管理员特权,可以在安装时创建事件来源。可以使用 .NET 安装程序类,通过 Windows 安装程序(如果使用 .msi 部署)或 InstallUtil.exe 系统实用程序(如果不使用 .msi 部署)可以将该类实例化。有关如何使用事件日志安装程序的详细信息,请参阅模块 10 构建安全的 ASP.NET 网页和控件。
如果在安装时无法创建事件来源,必须将权限添加到以下注册表项,并为 ASP.NET 进程帐户或任何模拟帐户(如果应用程序使用模拟)授予访问权限。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog
帐户必须至少具有以下权限:
•
查询键值
•
设置键值
•
创建子键
•
枚举子键
•
通知
•
读取
文件访问
应用程序所访问的任何文件在 ACL 中都必须具有访问控制项 (ACE),至少为 ASP.NET 进程帐户或模拟标识授予读取权限。通常,ACL 在目录上配置,然后文件继承该设置。
除了使用 NTFS 权限限制对文件和目录的访问以外,还可以使用 ASP.NET 信任级别对 Web 应用程序和 Web Services 进行限制,以限制它们可以访问文件系统的哪些区域。例如,中等信任的 Web 应用程序只能访问其自身的虚拟目录层次中的文件。
有关 ASP.NET CAS 策略的详细信息,请参阅模块 9 ASP.NET 代码访问安全性。
ACL 和权限
ASP.NET 进程帐户和(对于特定目录)任何模拟标识(如果应用程序使用模拟)需要以下 NTFS 权限。除了应用程序访问应用程序特定的文件系统资源所需的权限以外,还应使用表 Table 19.3 中所示的权限。
表 19.3:ASP.NET 进程帐户所需的 NTFS 权限
目录
所需权限
Temporary ASP.NET Files%windir%\Microsoft.NET\Framework\{版本}Temporary ASP.NET Files
进程帐户和模拟标识:
完全控制
临时目录 (%temp%)
进程帐户
完全控制
.NET Framework 目录%windir%\Microsoft.NET\Framework\{版本}
进程帐户和模拟标识:
读取和执行
列出文件夹内容
读取
.NET Framework 配置目录%windir%\Microsoft.NET\Framework\{版本}\CONFIG
进程帐户和模拟标识:
读取和执行
列出文件夹内容
读取
网站根目录
C:\inetpub\wwwroot
或默认网站指向的路径
进程帐户:
读取
系统根目录
%windir%\system32
进程帐户:
读取
全局程序集高速缓存
%windir%\assembly
进程帐户和模拟标识:
读取
内容目录
C:\inetpub\wwwroot\YourWebApp
进程帐户:
读取和执行
列出文件夹内容
读取
注意 对于 .NET Framework 1.0,直到文件系统根目录的所有父目录也都需要上述权限。父目录包括:
C:C:\inetpubC:\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 Services 所使用的存储过程。
以下过程假定使用的是镜像本地帐户,但对域帐户可以使用相同的方法来限制帐户在数据库中的能力。
•
为 ASP.NET 应用程序配置数据库访问权限
1.
使用计算机管理工具将 Web 服务器上本地 ASPNET 帐户的密码更改为已知的强密码。
为了可以在数据库服务器上创建镜像帐户,您需要执行此操作。
2.
在 Machine.config 中更改 <processModel> 元素上的 password 属性,使 ASP.NET 工作进程继续使用 ASPNET 帐户运行。使用 Aspnet_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 权限集不包含 ASP.NET Web 应用程序运行时所需的 AspNetHostingPermission,因此,如果不明确修改策略,应用程序将无法运行。
可以使用以下两种方法:
•
为驻留应用程序的 UNC 共享授予完全信任级别。
这是最简单的管理方法,如果运行 .NET Framework 1.0,则只能使用这种方法,因为 ASP.NET 1.0 Web 应用程序需要完全信任。
•
配置代码访问安全性策略,为代码授予 AspNetHostingPermission 及其可能需要的任何其他权限(根据代码所访问的资源类型和所执行的操作)。
由于 ASP.NET 动态创建代码和编译页面类的方式,在配置策略时必须对 UNC 和 Temporary ASP.NET Files 目录使用代码组。默认的临时目录为 \WINNT\Microsoft.NET\Framework\{版本}\Temporary ASP.NET Files,但可以使用 <compilation> 元素的 tempDirectory 属性为每个应用程序配置该位置。
有关 ASP.NET 代码访问安全性策略以及如何对特权代码进行沙盒处理的详细信息,请参阅模块 9 ASP.NET 代码访问安全性。
注意 配置策略时,应该为共享而不是区域授予信任级别(通过使用文件位置)。这样可以更加细化,因为不会影响到特定区域中的所有应用程序。
COM/DCOM 资源
应用程序在调用基于 COM 的资源(如服务型组件)时,将使用进程标识或模拟标识。客户端的身份验证和模拟级别是使用 Machine.config 中 <processModel> 元素上的 comAuthenticationLevel 和 comImpersonation 级别属性进行配置的。
有关详细信息和建议,请参阅模块 17 确保应用程序服务器的安全中的“企业服务注意事项”。
拒绝服务注意事项
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 ×î´ó POST ³¤¶È -->
<httpRuntime maxRequestLength="512"/>
</system.web>
注意 ASP.NET 不能解决数据包级的攻击。必须通过加强 TCP/IP 堆栈来解决数据包级的攻击。有关如何配置 TCP/IP 堆栈的详细信息,请参阅本指南“如何”部分中的如何:强化 TCP/IP 堆栈安全。
Web 场注意事项
如果 ASP.NET Web 应用程序在 Web 场中运行,不能保证由同一个 Web 服务器处理来自同一客户端的连续请求。这会影响到:
•
会话状态
•
加密和验证
•
DPAPI
会话状态
为了避免服务器的相互影响,可以将进程外的 ASP.NET 会话状态保留在 ASP.NET SQL Server 状态数据库中,或保留在远程计算机上运行的进程外状态服务中。有关如何确保远程状态存储中会话状态的安全的详细信息,请参与本文档前面的会话状态部分。
加密和验证
用于加密和验证表单身份验证 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 服务器上的配置机密,如数据库连接字符串。如果加密数据存储在远程服务器上(例如,在数据库中),应使用其他加密技术。有关如何将加密数据存储在数据库中的详细信息,请参阅模块 14 构建安全的数据访问。
安全 ASP.NET 应用程序的快照
以下快照视图显示了安全 ASP.NET 应用程序的属性,使您可以方便快捷地将设置与自己的配置进行比较。
表 19.4:安全 ASP.NET 应用程序配置的快照
组件
特性
进程标识
SP.NET 工作进程作为 ASPNET 运行:
<processModel username="machine"
password="AutoGenerate" />
自定义帐户(如果使用)是最小特权帐户。
自定义帐户的凭据在注册表中加密:
<processModel
userName="registry:HKLM\SOFTWARE\YourAppprocess\ASPNET_SETREG,userName"
password="registry:HKLM\SOFTWARE\YourAppprocess\ASPNET_SETREG,password"/>
模拟
模拟标识在注册表中加密:
<identity impersonate="true"
userName="registry:HKLM\SOFTWARE\YourAppidentity\ASPNET_SETREG,userName"
password="registry:HKLM\SOFTWARE\YourAppidentity\ASPNET_SETREG,password"/>
身份验证
网站分为公共访问区和受限制访问区。
表单身份验证配置是安全的:
<forms loginUrl="Restricted\login.aspx"
protection="All"
requireSSL="true"
timeout="10"
name="AppNameCookie"
path="/FormsAuth"
slidingExpiration="true" />
对身份验证 Cookie 进行加密和完整性检查。
身份验证 Cookie 需要使用 SSL。
如果不使用 SSL,应将滑动截止日期设置为 false。
会话寿命受限制。
Cookie 名称和路径是唯一的。
不使用 <credentials> 元素。
授权
ACL 是在 ASP.NET 资源上配置的。
配置 <authorization> 元素。
会话状态
禁用不需要的 ASP.NET 状态服务。
<sessionState mode="Off " />
与远程状态存储的通信通道已根据需要进行加密。
使用 Windows 身份验证连接 ASPState 数据库。
应用程序登录对 ASPState 数据库具有有限的访问权限。
连接参数(sqlConnectionString
和 stateConnectionString)在注册表中加密。
为非默认的端口配置 ASP.NET 状态服务。
视图状态
视图状态 MAC 在 Machine.config 中的 <pages> 元素上启用。
计算机密钥
validation 属性设置为 SHA1。
Web 服务器上运行的每个应用程序的密钥是唯一的。
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 Services
禁用不需要的 Web Services:
<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 目录受到保护。
(读取、写入和目录浏览权限已从 bin 中删除。
“执行”权限设置为“无”。)
身份验证设置已从 bin 目录中删除
小结
本模块通过重点介绍帐户、服务、协议、文件和目录等配置类别,以及在 Machine.config 和 Web.config 文件中维护的配置数据,说明如何确保 ASP.NET Web 应用程序或 Web Services 的安全。本模块还说明如何确保 ASP.NET Web 应用程序和 Web 服务器所依靠的不同功能区的安全,这些功能区包括身份验证、授权、会话状态和数据访问。
相关检查表,请参阅本指南“检查表”部分中的检查表:保护 ASP.NET 的安全。
其他资源
有关详细信息,请参阅以下资源和文章:
•
可以在 http://microsoft.com/downloads/details.aspx?FamilyId=06255A94-2635-4D29-A90C-28B282993A41&aylangs=en 下载 Web Services Enhancements (WSE) 1.0 SP1 for Microsoft .NET(英文)。
•
Microsoft 知识库文章 329290 How To:Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings(英文)。
•
Microsoft 知识库文章 311209 How To:Configure ASP.NET for Persistent SQL Server Session State Management(英文)。
•
Microsoft 知识库文章 312906 How To:Create Keys by Using Visual C# .NET for Use in Forms Authentication(英文)。
•
“How To:Implement Kerberos Delegation for Windows 2000”,该内容在“Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications:Authentication, Authorization, and Secure Communication”的“How To”部分,其网址为:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT05.asp(英文)。
•
有关 Open Hack 竞赛的安全注意事项的详细信息,请参阅 MSDN 文章构建和配置更安全的网站。