确保 ASP.NET 应用程序和 Web Services 的安全

转自:microsoft TechNet

更新日期: 2004年04月12日
本页内容
本模块内容本模块内容
目标目标
适用范围适用范围
如何使用本模块如何使用本模块
方法方法
必备知识必备知识
描述 Machine.Config 和 Web.Config描述 Machine.Config 和 Web.Config
Machine.Config 和 Web.Config 指南Machine.Config 和 Web.Config 指南
ASP.NET 中的信任级别ASP.NET 中的信任级别
ASP.NET 的进程标识ASP.NET 的进程标识
模拟模拟
身份验证身份验证
授权授权
会话状态会话状态
视图状态视图状态
计算机密钥计算机密钥
调试调试
跟踪跟踪
异常管理异常管理
远程处理远程处理
Web ServicesWeb Services
禁止访问的资源禁止访问的资源
bin 目录bin 目录
事件日志事件日志
文件访问文件访问
ACL 和权限ACL 和权限
注册表注册表
数据访问数据访问
UNC 共享UNC 共享
COM/DCOM 资源COM/DCOM 资源
拒绝服务注意事项拒绝服务注意事项
Web 场注意事项Web 场注意事项
安全 ASP.NET 应用程序的快照安全 ASP.NET 应用程序的快照
小结小结
其他资源其他资源

本模块内容

安 全的 ASP.NET Web 应用程序依赖于完全安全的网络、主机和平台基础结构。当上述条件满足后,攻击者将尝试利用 Web 应用程序和 Web Services(通常在端口 80 上侦听)中的漏洞。如果未有效配置 Web 应用程序,攻击者可能会获得系统的访问权限并利用系统。

作为管理员,您必须检查默认的计算机级配置和各个应用程序配置,以处理和删除所有漏洞或不安全设置。

本 模块从系统管理员的角度描述了 ASP.NET 中的新增内容,并描述了如何配置计算机范围和应用程序特定的安全设置。此外,本模块还提供了确保 ASP.NET Web 应用程序和 Web Services 安全的方法,这种方法是为确保网络、应用程序服务器、数据库服务器和 Web 服务器安全而推荐的方法的补充。

目标

使用本模块可以实现:

使用 Aspnet_setreg.exe 实用程序在注册表中存储凭据和连接字符串。

使用配置文件 (*.config) 管理 Web 应用程序环境。

了解如何分层实施和处理 Machine.config 和 Web.config。

锁定配置设置。

强制实施计算机范围和 Web 应用程序安全策略。

使用 <location> 元素自定义文件和目录安全设置。

确保 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 应用程序的主要安全注意事项。为了充分理解本模块内容,请:

阅读模块 16 保护 Web 服务器。本模块描述了如何确保 Windows 2000 操作系统和 Microsoft .NET Framework 的安全。安全的基础平台是确保 ASP.NET Web 应用程序或 Web Services 安全的前提。

使用快照。表 19.4(在本模块结尾部分)中显示了安全 ASP.NET 应用程序的快照,该应用程序在 Machine.config 和 Web.config 中具有安全的配置设置。可在配置服务器和应用程序设置时使用此表。

使用检查表。本指南“检查表”部分的检查表:保护 ASP.NET 的安全提供了可打印的作业指导,以供快速参考。使用基于任务的检查表可以快速评估需要哪些步骤,并帮助您逐步完成各个步骤。

要 获取相关指南,请阅读模块 20 驻留多个 ASP.NET 应用程序,本模块描述了如何将同一服务器上运行的多个 Web 应用程序与重要的系统资源隔离,以及如何将各个 Web 应用程序彼此隔离。有关配置部分信任 Web 应用程序和 Web Services 的代码访问安全性 (CAS) 策略的详细信息,请参阅模块 9 ASP.NET 代码访问安全性。

方法

要确保 ASP.NET 应用程序的安全,应先强化操作系统和 .NET Framework 安装基准,然后应用安全的应用程序配置设置,以减小应用程序的受攻击面。

这些措施包括:

服务。.NET Framework 安装了 ASP.NET 状态服务,以管理进程外的 ASP.NET 会话状态。请确保 ASP.NET 状态服务的安全(如果已安装该服务)。如果不需要,请禁用 ASP.NET 状态服务。

协议。限制 Web Services 协议以减小攻击面。

帐户。创建默认的 ASPNET 帐户,用来运行 Web 应用程序、Web Services 和 ASP.NET 状态服务。如果创建自定义帐户以运行进程或服务,必须将其配置为最小特权用户,使其具有必需的 NTFS 权限和 Windows 特权的最小集合。

文件和目录。应确保用来保存私有程序集的应用程序 bin 目录的安全,以降低攻击者下载业务逻辑的风险。

配置存储。许多控制功能区域(如验证、授权、会话状态等)的安全相关设置在 Machine.config 和 Web.config XML 配置文件中进行维护。要确保 ASP.NET 应用程序的安全,必须使用安全的配置设置。

必备知识

在采取措施确保 Web 应用程序和 Web Services 的安全之前,应该了解一些基本注意事项和详细信息。

ASP.NET 处理模块

在 Microsoft Windows 2000 中,Internet 信息服务 (IIS) 5.0 在 ASP.NET 工作进程 (Aspnet_wp.exe) 中运行所有的 Web 应用程序和 Web Services。隔离单元是应用程序域,每个虚拟目录都有自己的应用程序域。进程级的配置设置由 Machine.config 中的 <processModel> 元素维护。

在 Microsoft Windows Server 2003 中,IIS 6.0 应用程序池允许使用单独的进程隔离应用程序。有关详细信息,请参阅模块 20 驻留多个 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> 元素:

<!--运行前-->
<processModel userName="CustomAccount" password="Str0ngPassword" />
<!--运行后-->
<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 为系统、管理员和创建者所有者授予完全控制权限。如果使用工具加密 <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 应用程序不使用模拟,因为它会给设计、实现和可伸缩性带来负面影响。例如,使用模拟会阻碍有效的中间层连接池,这将限制应用程序的可伸缩性。模拟对于特定 方案非常有用,例如,当应用程序使用匿名用户帐户的安全上下文访问资源时。在同一服务器上驻留多个应用程序时,这是一项常用技术。有关详细信息,请参阅模 块 20 驻留多个 Web 应用程序。

HttpForbiddenHandler、Urlscan 和 404.dll

可 以使用很多技术来阻止对受限制资源的访问。ASP.NET 提供了 HttpForbiddenHandler,可以将不应通过 HTTP 下载的 ASP.NET 文件类型映射到 HttpForbiddenHandler。可以使用 <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 的详细信息,请参阅模块 16 保护 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 标记区分大小写,请确保使用正确的大小写形式。

图 19.1 显示了管理员可以使用的用于配置 ASP.NET Web 应用程序的配置文件。

ASP.NET 配置文件

图 19.1
ASP.NET 配置文件

Machine.config 和 Web.config 文件共享许多相同的配置部分和 XML 元素。Machine.config 用于将计算机范围的策略应用到本地计算机上运行的所有 .NET Framework 应用程序。开发人员还可以使用应用程序特定的 Web.config 文件自定义单个应用程序的设置。

注意 Windows 可执行文件(如 WinForm 应用程序)是使用配置文件进行配置的。这些文件的名称源自应用程序可执行文件的名称,例如,App.exe.config,其中“app”是应用程序名。

对配置文件所作的更改将被动态应用,通常无需重启服务器或任何服务,除非更改了 Machine.config 中的 <processModel> 元素,本模块稍后将讨论此元素。

表 19.1 显示了配置文件的位置。

表 19.1:配置文件的位置

配置文件位置

Machine.config
(每台计算机每个 .NET Framework 安装版一个

%windir%/Microsoft.NET/Framework/{version}/CONFIG

Web.config
(每个应用程序有零个、一个或多个)

/inetpub/wwwroot/web.config
/inetpub/wwwroot/YourApplication/web.config
/inetpub/wwwroot/YourApplication/SubDir/web.config

Enterprisesec.config
(企业级 CAS 配置)

%windir%/Microsoft.NET/Framework/{version}/CONFIG

Security.config
(计算机级 CAS 配置)

%windir%/Microsoft.NET/Framework/{version}/CONFIG

Security.config
(用户级 CAS 配置)

/Documents and Settings/{user}/Application
Data/Microsoft/CLR Security Config/{version}

Web_hightrust.config
Web_mediumtrust.config
Web_lowtrust.config
Web_minimaltrust.config
(ASP.NET Web 应用程序 CAS 配置)

%windir%/Microsoft.NET/Framework/{version}/CONFIG

有关 ASP.NET Web 应用程序 CAS 配置文件的详细信息,请参阅模块 9 ASP.NET 代码访问安全性。

分层策略评估

对 于集中式管理,可以在 Machine.config 中应用设置。Machine.config 中的设置可以定义计算机范围的策略,也可用来通过 <location> 元素应用应用程序特定的配置。开发人员可以提供应用程序配置文件,来覆盖计算机策略的某些方面。对于 ASP.NET Web 应用程序,Web.config 文件位于应用程序的虚拟根目录中,也可以位于虚拟根目录下的子目录中(可选)。请考虑图 19.2 中显示的安排。

分层配置

图 19.2
分层配置

在 图 19.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> 元素清除父级设置。

下表显示了对于图 19.2 中应用的 Web 请求组合,组合配置设置是从何处获取的。

表 19.2:应用配置设置

HTTP 请求组合设置来自

http://Server/AppRoot

Machine.config
Web.config (AppRoot v-dir)

http://Server/AppRoot/SubDir1

Machine.config
Web.config (AppRoot v-dir)
Web.config (SubDir1)

http://Server/AppRoot/SubDir2

Machine.config
Web.config (AppRoot v-dir)

http://Server/Subdir2

Machine.config

<location>

<location> 元素主要用于三个目的:

将配置设置应用于特定的应用程序文件。

通过在 Machine.config 中应用应用程序特定的设置进行集中管理。

锁定配置设置以阻止应用程序级覆盖。

可以在 Machine.config 或 Web.config 中使用 <location> 标记。对于 Machine.config,如果指定路径,必须完全限定该路径,使其包括网站名和虚拟目录名,还可以包括子目录和文件名(可选)。例如:

<location path="Web Site Name/VDirName/SubDirName/PageName.aspx" > 
<system.web>
. . .
</system.web>
</location>

注意 使用 Machine.config 的位置标记时,必须包括网站名。

对于 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>
... 计算机范围的默认值
</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 文件。尽管可以使用多个 <location> 元素从 Machine.config 配置单个应用程序,但单独的 Web.config 文件可以提供部署优势,并能使 Machine.config 文件变得更小。

需要考虑的主要问题是计算机策略应该强制使用哪些设置。这取决于特定的方案。一些通用方案如下所示:

Windows 身份验证考虑一个企业的 Intranet 门户方案,在这个方案中,您希望将验证与应用程序分离,并由组织通过 Active Directory 控制验证。在此方案中,可以强制使用 Windows 身份验证,但允许单个应用程序模拟以下配置:

<location path="" allowOverride="false"> 
<system.web>
<authentication mode="Windows"/>
</system.web>
</location>

驻留方案提 供驻留服务的公司需要限制应用程序,以使它们不能访问彼此的资源,从而限制对重要系统资源的访问。要实现此目标,可以配置所有应用程序以部分信任级别运 行。例如,中级信任级别限制应用程序只能访问自身虚拟目录分级结构内的文件,而限制对其他类型资源的访问。有关详细信息,请参阅模块 9 ASP.NET 代码访问安全性。要对服务器上的所有应用程序应用中级信任策略,请使用以下配置:

<location path="" allowOverride="false> 
<system.web>
<trust level="Medium" />
</system.web>
</location>

ACL 和权限

配置文件包含敏感数据,因此需要使用适当配置的 ACL 来限制访问。

Machine.config

默认情况下,使用以下 ACL 配置 Machine.config:

Administrators:完全控制
System:完全控制
Power Users:修改
Users:读取和执行
LocalMachine/ASPNET(进程标识):读取和执行

注意 在 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,默认情况下,该 ACL 将为 Everyone 组的成员授予读取权限。要锁定应用程序特定的 Web.config,请使用以下 ACL 之一。

对于 .NET Framework 1.0:

Administrators:完全控制
System:完全控制
ASP.NET 进程标识:读取
UNC 标识:读取
模拟标识(固定标识):读取
模拟标识(原呼叫方):读取

对于 .NET Framework 1.1:

Administrators:完全控制
System:完全控制
ASP.NET 进程标识:读取
UNC 标识:读取
模拟标识(固定标识):读取

如果应用程序使用明确帐户的模拟(即,如果模拟固定标识),如 <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> 元素配置应用程序的信任级别。 默认情况下,配置级别设置为“完全”,如下所示:

<!--  level="[Full|High|Medium|Low|Minimal]" --> 
<trust level="Full" originUrl=""/>

这意味着应用程序被授予完全、无限制的 CAS 权限。使用这种配置,应用程序执行的资源访问成功与否只取决于操作系统安全性。

如果将信任级别更改为“完全”以外的级别,可能会破坏依赖于访问资源类型和执行操作类型的现有 ASP.NET Web 应用程序。应该在每个信任级别上对应用程序进行全面彻底的测试。

有关生成使用 CAS 的部分信任 Web 应用程序的详细信息,请参阅模块 9 ASP.NET 代码访问安全性。有关使用信任级别提供应用程序隔离的详细信息,请参阅模块 20 驻留多个 ASP.NET Web 应用程序。

ASP.NET 的进程标识

ASP.NET Web 应用程序和 Web Services 在 ASP.NET 工作进程 (Aspnet_wp.exe) 的共享实例中运行。进程级别的设置(包括进程标识)使用 Machine.config 中的 <processModel> 元素进行配置。

<processModel>

ASP.NET 工作进程的标识使用 <processModel> 元素上的userName 和 password 属性进行配置。配置进程标识时:

使用默认 ASPNET 帐户

使用最小特权自定义帐户

加密 <processModel> 凭据

不将 ASP.NET 作为 SYSTEM 运行

使用默认 ASPNET 帐户

本地 ASPNET 帐户是默认的最小特权帐户,专用于运行 ASP.NET Web 应用程序和 Web Services。如果可以,请通过以下默认配置使用此帐户:

<processModel enable="true" userName="machine" password="AutoGenerate" ...  /> 
使用最小特权自定义帐户

如果必须使用备用标识运行 ASP.NET 工作进程,请确保将所使用的帐户配置为最小特权帐户。这可以限制攻击者设法使用进程安全上下文执行代码所带来的损害。

您可能决定使用备用帐户,因为您需要使用 Windows 身份验证连接到远程 Microsoft SQL Server™ 数据库或网络资源。请注意,可以使用本地 ASPNET 帐户执行上述操作。有关详细信息,请参阅本模块后面的数据访问

有关 ASP.NET 进程帐户所需的 NTFS 权限的详细信息,请参阅本模块后面的 ACL 和权限

还应将以下用户权限授予 ASP.NET 进程帐户:

从网络访问此计算机

作为批作业登录。

作为服务登录。

拒绝本地登录。

拒绝通过终端服务登录。

加密 <processModel> 凭据

如果您需要使用自定义帐户,请不要在 Machine.config 中存储纯文本凭据。应使用 Aspnet_setreg.exe 实用程序在注册表中存储加密的凭据。

加密 <processModel> 的凭据

1.

从命令提示符处运行以下命令:

aspnet_setreg -k:Software/YourApp/process -u:CustomAccount :p:StrongPassword 

此命令会将加密的连接字符串存储在指定的注册表项中,并通过受限制的 ACL 来确保注册表项的安全,该 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 How To:Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings(英文)。

不要将 ASP.NET 作为 SYSTEM 运行

不要使用 SYSTEM 帐户运行 ASP.NET,也不要为 ASP.NET 进程帐户授予“作为操作系统的一部分工作”用户权限。此操作消除了最小特权原则,从而增大了攻击者使用 Web 应用程序的进程安全上下文执行代码所带来的损害。

模拟

默认情况下,ASP.NET 应用程序不使用模拟。当应用程序访问 Windows 资源时,将使用 ASP.NET 工作进程帐户(默认情况下为 ASPNET)的安全上下文。

<identity>

<identity> 元素用于启用模拟。可以模拟:

原呼叫方(IIS 验证过的标识)

固定标识

模拟原呼叫方

要模拟原呼叫方,请使用以下配置:

<identity impersonate="true" />

模拟使用 IIS 提供的代表已验证呼叫方的访问令牌。这可以是匿名 Internet 用户帐户(例如,如果应用程序使用表单身份验证),也可以是代表原呼叫方的 Windows 帐户(如果应用程序使用 Windows 身份验证)。

如果确实要启用原呼叫方模拟,请注意以下问题:

由于数据库连接不能被有效汇集,因此会降低应用程序的可伸缩性。

由于需要为单个用户配置后端资源上的 ACL,因此会增加管理工作量。

委派需要 Kerberos 身份验证和适当配置的 Windows 2000 环境。

有 关详细信息,请参阅“Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication”的“How To”部分中的“How To: Implement Kerberos Delegation for Windows 2000”,其网址为:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT05.asp(英文)。

模拟固定标识

要模拟固定标识,请使用 <identity> 元素上的 userName 和 password 属性指定标识:

<identity impersonate="true" userName="MyServiceAccount"  
password="Str0ng!Passw0rd"/>

请不要以纯文本形式存储此处所示的凭据。应使用 Aspnet_setreg.exe 工具加密凭据并将其存储在注册表中。

加密 <identity> 的凭据

1.

从命令提示符处运行以下命令:

aspnet_setreg -k:Software/YourApp/identity -u:CustomAccount :p:StrongPassword 

此命令会将加密的连接字符串存储在指定的注册表项中,并通过受限制的 ACL 来确保注册表项的安全,该 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 How To:Use the ASP.NET Utility to Encrypt Credentials and Session State Connection Strings(英文)。

作为操作系统的一部分工作

当 通过指定 userName 和 password 属性模拟固定标识时,ASP.NET 1.0 进程帐户在 Windows 2000 上需要具有“作为操作系统的一部分工作”用户权限。由于这可以有效地将 ASP.NET 进程帐户提升为可以访问本地系统帐户的特权级别,因此 ASP.NET 1.0 不推荐使用模拟固定标识。

注意:如果正在 Windows 2000 或 Windows 2003 Server 上运行 ASP.NET 1.1,则不需要此用户权限。

NTFS 权限要求

必须为模拟标识适当配置 NTFS 权限。有关详细信息,请参阅本模块后面的“ACL 和权限”。

身份验证

<authentication> 元素配置应用程序使用的验证模式。

<authentication>

适当的身份验证模式取决于应用程序或 Web Services 是如何设计的。默认的 Machine.config 设置应用安全的 Windows 身份验证默认值,如下所示:

<!-- 验证属性:
mode="[Windows|Forms|Passport|None]" -->
<authentication mode="Windows" />

表单身份验证指南

要使用表单身份验证,请在 <authentication> 元素上设置 mode="Forms" 。接下来,使用 <forms> 子元素配置表单身份验证。以下代码片断显示了安全的 <forms> 身份验证元素配置:

<authentication mode="Forms">  
<forms loginUrl="Restricted/login.aspx" SSL 保护文件夹中的登录页
protection="All" 私密性和完整性
requireSSL="true" 阻止通过 http 发送 Cookie
timeout="10" 限制会话寿命
name="AppNameCookie" 每个应用程序唯一的名称
path="/FormsAuth" 和路径
slidingExpiration="true" > 滑动会话寿命
</forms>
</authentication>

使用以下建议提高表单身份验证的安全性:

对网站进行分区

设置 protection="All"

使用小 Cookie 超时值

考虑使用固定的有效期.

对表单身份验证使用 SSL.

如果不使用 SSL,请设置 set slidingExpiration = "false"

不要在生产服务器上使用 <credentials> 元素

配置 <machineKey> 元素

使用唯一的 Cookie 名称和路径

对网站进行分区

可 以将网站的公共访问区和受限制访问区分开。将只允许通过身份验证的用户访问的应用程序登录页和其他页面以及资源放在一个单独的文件夹中,与公共访问区分 开。通过在 IIS 中配置子文件夹要求 SSL 访问权限来保护受限制的子文件夹,然后使用 <authorization> 元素来限制访问并强制登录。例如,以下 Web.config 配置允许任何人访问当前目录(这提供了公共访问权限),但阻止未经授权的用户访问受限制的子文件夹。任何访问尝试都会强制表单登录。

<system.web>
<!-- 虚拟目录根文件夹中包含普通页面。
未经过身份验证的用户可以查看这些页面,并且无需
使用 SSL 进行保护。 -->
<authorization>
<allow users="*" />
</authorization>
</system.web>

<!-受限制文件夹只能用于验证和 SSL 访问。 -->
<location path="Restricted" >
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>

有关其他编程注意事项的信息(例如,如何在受限制页面和非限制页之间导航),请参阅模块 10 生成 ASP.NET 网页和控件中的“表单身份验证”。

Set Protection="All"

此设置可以确保加密表单身份验证 Cookie,以提供私密性和完整性。用于 Cookie 加密的密钥和算法是在 <machineKey> 元素上指定的。

加 密和完整性检查可防止 Cookie 篡改,但如果攻击者设法捕获 Cookie,这并不能降低 Cookie 重播攻击的风险。还可以使用 SSL 通过网络监视软件来阻止攻击者捕获 Cookie。尽管使用 SSL,Cookie 仍会被跨站点脚本 (XSS) 攻击窃取。应用程序必须采取充分的预防措施以及适当的输入验证策略来降低此风险。

使用小 Cookie 超时值

可以使用小超时值限制会话寿命,从而降低窗口遭受 Cookie 重播攻击的风险。

考虑使用固定的有效期

考虑在 <forms> 元素上设置 slidingExpiration="false",使 Cookie 的截止日期固定,而不是在每个 Web 请求之后重置有效期。如果未使用 SSL 保护 Cookie,这一点很重要。

注意 .NET Framework 1.1 中提供此功能。

将 SSL 用于表单身份验证

可以使用 SSL 保护凭据和身份验证 Cookie。SSL 可阻止攻击者捕获用于向应用程序证明您的身份的凭据或表单身份验证 Cookie。窃取身份验证 Cookie 是窃取登录。

设置 requireSSL="true"。这将设置 Cookie 中的 Secure 属性,该属性可确保不通过 HTTP 链接将 Cookie 从浏览器传送到服务器。要求使用 HTTPS (SSL)。

注意 这是 .NET Framework 1.1 的设置。它采用明确的编程,在基于 1.0 版本构建的应用程序中设置 Cookie 的 Secure 属性。有关详细信息和示例代码,请参阅模块 10 生成安全的 ASP.NET 网页和控件。

如果不使用 SSL,请设置 slidingExpiration = "false"

通 过将 slidingExpiration 设置为 false,可以将 Cookie 的超时期限固定为自初始创建 Cookie 之后的某段时间(以分钟表示)。否则,应该针对每个 Web 服务器请求更新超时时间。如果 Cookie 被捕获,它将为攻击者提供足够的时间,使其作为已通过身份验证的用户来访问您的应用程序。

注意 在 .NET Framework 1.1 中提供了此项功能。

不要在生产服务器上使用 <credentials> 元素

可以在 XML 配置文件中存储用户凭据,以支持快速开发和有限测试。请不要使用实际的最终用户凭据。最终用户凭据不应存储在生产服务器上的配置文件中。生产应用程序应该实现自定义用户凭据存储,例如,在 SQL Server 数据库中。

配置 MachineKey

<machineKey> 元素定义了用于加密表单身份验证 Cookie 的加密算法。此元素也可用于维护加密密钥。有关详细信息,请参阅本模块的计算机密钥部分。

使用唯一的 Cookie 名称和路径

唯一的 name 和 path 属性值。确保名称具有唯一性,可以防止在同一服务器上驻留多个应用程序时出现问题。

授权

除非用户具有明确的资源访问权限,如特殊的网页、资源文件、目录等,否则配置在默认情况下应该拒绝访问。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>   
<!-- 允许/拒绝属性:
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,机构名和组名是区分大小写的。组名必须与出现在 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 来确保注册表项的安全,该 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:/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 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/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"/>

身份验证

网站分为公共访问区和受限制访问区。
表单身份验证配置是安全的:

<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 的安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值