19.4 ASP.NET

本节主要介绍在ASP.NET平台上获取用户提交的输入的方法、与用户会话交互的方式、其中存在的潜在危险的API以及与平台安全相关的配置选项。

19.4.1 确定用户提交的数据

ASP.NET 应用程序通过System.Web.HttpRequest类获取用户提交的输入。这个类中包含大量Web应用程序用于访问用户提交的数据的属性和方法。表19-4列出的API可用于获取用户请求中的数据。

表19-4 ASP.NET平台中用于获取用户提交的数据的API

API 描 述
Params 以String名称与String值的形式保存URL查询字符串、POST请求主体、HTTP
cookie以及其他服务器变量中的参数。这个属性返回这些参数类型的集合
Item 返回Param集合中的命名项
Form 返回用户提交的表单变量名称与变量值集合
QueryString 返回请求查询字符串中变量名称与变量值的集合
ServerVariables 返回大量ASP服务器变量(类似于CGI变量)名称与变量值的集合,包括请求原始
数据、查询字符串、请求方法、HTTP Host消息头等
Headers 以String名称与String值之间的映射的形式保存请求中的HTTP消息头,使用这
个属性可以访问该映射
Url
RawUrl
这些属性返回请求中的URL信息,包括查询字符串
UrlReferer 返回与在请求的HTTP Referer消息头中指定的URL有关的信息
Cookies 返回Cookie对象的集合,其中包含请求所收到的cookie的信息,包括它们的名称
与值
Files 返回用户上传的文件集合
InputStream
BinaryRead
这些API返回客户端送出的原始请求的不同表示形式,因此可用于访问其他所有API
获得的任何信息
HttpMethod 返回HTTP请求所使用的方法
Browser
UserAgent
返回用户浏览器的信息,与在HTTP User-Agent消息头中提交的信息类似
AcceptTypes 返回客户端支持的MIME类型的字符串数组,与在HTTP Accept消息头中提交的信
息类似
UserLanguages 返回包含客户端所接受的语言的字符串数组,与在HTTP Accept-Language消息
头中提交的信息类似

19.4.2 会话交互

ASP.NET应用程序以各种方式与用户会话进行交互,以保存和检索信息。

使用Session属性可轻松保存和检索当前会话中的信息。这个属性的访问方式与任何其他索引集合类似:

img553a

ASP.NET个性化配置与Session属性的用法非常相似,其唯一不同之处在于,前者相对于一个特定的用户,因此在相同用户的不同会话中持续保存不变。在不同的会话中,用户的身份通过验证机制或一个特殊的持久性cookie得以重新确认。在用户个性化配置中,数据以下列方式保存和检索:

img553b

另外,System.Web.SessionState.HttpSessionState类也可用于保存和检索会话中的信息。它以字符串名称与对象值之间映射的方式保存信息,使用表19-5中列出的API可以访问这个映射。

表19-5 ASP.NET平台中用于与用户会话交互的API

API 描 述
Add 在会话集合中增加一个数据项
Item 获取或设定集合中命名数据项的值
Keys
GetEnumerator
返回集合中所有数据项的名称
CopyTo 将值组成的集合复制到数组中

19.4.3 潜在危险的API

这一节介绍一些常见的ASP.NET API。以危险的方式使用这些API可能会造成安全漏洞。

1.文件访问

System.IO.File是用于访问ASP.NET文件最主要的类。它的所有方法都是静态的,并且没有公共构造函数。

这个类的37个方法全都接受一个文件名作为参数。如果未检查其中是否包含点-点-斜线序列,就提交用户可控制的数据,就会造成路径遍历漏洞。例如,下面的代码将打开Windows C:\ 驱动器根目录下的一个文件:

img554a

下面的类常用于读取与写入文件内容:

img002 System.IO.FileStream

img002 System.IO.StreamReader

img002 System.IO.StreamWriter

它们的各种构造函数接受一个文件路径作为参数。如果提交用户可控制的数据,这些构造函数可能引入路径遍历漏洞。例如:

img554b

2.数据库访问

ASP.NET有许多用于访问数据库的API,下面的类主要用于建立并执行SQL语句:

img002 System.Data.SqlClient.SqlCommand

img002 System.Data.SqlClient.SqlDataAdapter

img002 System.Data.Oledb.OleDbCommand

img002 System.Data.Odbc.OdbcCommand

img002 System.Data.SqlServerCe.SqlCeCommand

其中每个类都有一个构造函数,它接受一个包含SQL语句的字符串;而且每个类都有一个CommandText属性,可用于获取并设定SQL语句的当前值。如果适当地配置一个命令对象,通过调用Execute方法即可执行SQL语句。

如果用户提交的数据属于以查询执行的字符串的一部分,那么应用程序可能易于受到SQL注入攻击。例如:

img555a

它会执行不良查询:

img555b

上面列出的每一个类通过它们的Parameters属性支持预处理语句,允许应用程序创建一个包含参数占位符的SQL语句,并以可靠且类型安全的方式设定这些占位符的值。如果按正常的方式使用,这种机制就不易受到SQL注入攻击。例如:

img555c

它生成的查询等同于:

img555d

3.动态代码执行

VBScript函数Eval接受一个包含VBScript表达式的字符串自变量。该函数求出这个表达式的值,并返回结果。如果用户可控制的数据被合并到要计算值的表达式中,那么用户就可以执行任意命令或修改应用程序的逻辑。

函数Execute和ExecuteGlobal接受一个包含ASP代码的字符串,这个ASP代码与直接出现在脚本中的代码的执行方式完全相同。冒号分隔符用于将几个语句连接在一起。如果向Execute函数提交用户可控制的数据,那么攻击者就可以在应用程序中执行任意命令。

4.OS命令执行

下面的API可以各种方式在ASP.NET应用程序中运行外部进程:

img002 System.Diagnostics.Start.Process

img002 System.Diagnostics.Start.ProcessStartInfo

在对对象调用Start之前,可以向静态Process.Start方法提交一个文件名字符串,或者用一个文件名配置Process对象的StartInfo属性。如果文件名字符串可完全由用户控制,那么应用程序几乎可以肯定易于受到任意命令执行攻击。例如,下面的代码将运行Windows calc程序:

img556a

然而,如果用户仅能够控制提交给Start的部分字符串,那么应用程序仍然可能易于受到攻击。例如:

img556b

API并不解释& 与 | 等 shell元字符,也不接受文件名参数中的命令行参数,因此,如果用户仅控制文件名参数的一部分,这种攻击是唯一能够成功的攻击。

已被启动的进程的命令行参数可以使用ProcessStartInfo类的Arguments属性设定。如果只有 Arguments参数可由用户控制,应用程序仍然易于受到除代码执行以外的其他攻击。例如,如果应用程序以用户可控制的参数作为目标URL执行wget程序,那么攻击者就可以向wget进程提交危险的命令行参数,例如,致使它下载一个文档,并将该文档保存在文件系统中的任何位置。

5.URL重定向

下面的API用于在ASP.NET中发布一个HTTP重定向:

img002 System.Web.HttpResponse.Redirect

img002 System.Web.HttpResponse.Status

img002 System.Web.HttpResponse.StatusCode

img002 System.Web.HttpResponse.AddHeader

img002 System.Web.HttpResponse.AppendHeader

img002 Server.Transfer

通常,使用HttpResponse.Redirect方法可以引起一个重定向响应,该方法接受一个包含相对或绝对URL的字符串。如果这个字符串的值由用户控制,那么应用程序可能易于受到钓鱼攻击。

还必须确保检查Status/StatusCode属性与AddHeader/AppendHeader方法的用法。如果某个重定向包含一个含有HTTP Location消息头的3xx响应,应用程序就可能使用这些API执行重定向。

Server.Transfer方法有时也可用于实现重定向。实际上,这个方法并不能实现HTTP重定向,而是应根据当前请求修改被服务器处理的页面。因此,不能通过破坏它重定向到一个站外URL;这个方法对攻击者而言并没有多大用处。

6.套接字

System.Net.Sockets.Socket类用于创建网络套接字。创建一个Socket对象后,再通过调用Connect方法连接这个对象;该方法接受目标主机的IP与端口信息为参数。如果用户能够以某种方式控制这些主机信息,攻击者就可以利用应用程序与任意主机建立网络连接,无论这些主机位于因特网上、私有DMZ中还是在应用程序上运行的内部网络内。

19.4.4 配置ASP.NET环境

Web根目录下的web.config XML文件包含ASP.NET环境的配置设置,它还控制着应用程序的 行为,如表19-6所示。

表19-6 ASP.NET环境中与安全有关的配置设置

设 置 描 述
httpCookies 这个元素决定与cookie有关的安全设置。如果httpOnlyCookies属性为真,那么cookie将被
标记为HttpOnly,因而不能被客户端脚本直接访问。如果requireSSL属性为真,cookie
将被标记为secure,因此只能由浏览器通过HTTPS请求传送
sessionState 这个元素决定会话的行为。timeout属性的值决定一个空闲会话的到期时间(单位:分钟)。
如果regenerateExpiredSessionId元素设为true(默认情况),那么在收到一个到期
会话ID后,将发布一个新的会话ID
compilation 这个元素决定是否将调试符号编译到页面中,生成更详细的调试错误信息。如果debug属性
为true,调试符号将包含在页面中
customErrors 这个元素决定,如果发生无法处理的错误,应用程序是否返回详细的错误消息。如果mode属
性为On或RemoteOnly,那么应用程序用户将收到被属性defaultRedirect确认的页面,
而不是系统生成的详细消息
httpRuntime 这个元素决定各种运行时设置。如果enableHeaderChecking属性为true(默认情况),
ASP.NET将在请求消息头中检查潜在的注入攻击,包括跨站点脚本。如果enable-VersionHeader
属性为true(默认情况),ASP.NET将输出一个详细的版本字符串,攻击
者可利用它在特定版本的平台中搜索漏洞

如果数据库连接字符串之类的敏感数据保存在配置文件中,应使用ASP.NET“受保护配置”特性加密这些数据。