本节主要介绍在ASP.NET平台上获取用户提交的输入的方法、与用户会话交互的方式、其中存在的潜在危险的API以及与平台安全相关的配置选项。
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消息 头中提交的信息类似 |
ASP.NET应用程序以各种方式与用户会话进行交互,以保存和检索信息。
使用Session属性可轻松保存和检索当前会话中的信息。这个属性的访问方式与任何其他索引集合类似:
ASP.NET个性化配置与Session属性的用法非常相似,其唯一不同之处在于,前者相对于一个特定的用户,因此在相同用户的不同会话中持续保存不变。在不同的会话中,用户的身份通过验证机制或一个特殊的持久性cookie得以重新确认。在用户个性化配置中,数据以下列方式保存和检索:
另外,System.Web.SessionState.HttpSessionState类也可用于保存和检索会话中的信息。它以字符串名称与对象值之间映射的方式保存信息,使用表19-5中列出的API可以访问这个映射。
表19-5 ASP.NET平台中用于与用户会话交互的API
API | 描 述 |
---|---|
Add | 在会话集合中增加一个数据项 |
Item | 获取或设定集合中命名数据项的值 |
Keys GetEnumerator |
返回集合中所有数据项的名称 |
CopyTo | 将值组成的集合复制到数组中 |
这一节介绍一些常见的ASP.NET API。以危险的方式使用这些API可能会造成安全漏洞。
1.文件访问
System.IO.File是用于访问ASP.NET文件最主要的类。它的所有方法都是静态的,并且没有公共构造函数。
这个类的37个方法全都接受一个文件名作为参数。如果未检查其中是否包含点-点-斜线序列,就提交用户可控制的数据,就会造成路径遍历漏洞。例如,下面的代码将打开Windows C:\ 驱动器根目录下的一个文件:
下面的类常用于读取与写入文件内容:
System.IO.FileStream
System.IO.StreamReader
System.IO.StreamWriter
它们的各种构造函数接受一个文件路径作为参数。如果提交用户可控制的数据,这些构造函数可能引入路径遍历漏洞。例如:
2.数据库访问
ASP.NET有许多用于访问数据库的API,下面的类主要用于建立并执行SQL语句:
System.Data.SqlClient.SqlCommand
System.Data.SqlClient.SqlDataAdapter
System.Data.Oledb.OleDbCommand
System.Data.Odbc.OdbcCommand
System.Data.SqlServerCe.SqlCeCommand
其中每个类都有一个构造函数,它接受一个包含SQL语句的字符串;而且每个类都有一个CommandText属性,可用于获取并设定SQL语句的当前值。如果适当地配置一个命令对象,通过调用Execute方法即可执行SQL语句。
如果用户提交的数据属于以查询执行的字符串的一部分,那么应用程序可能易于受到SQL注入攻击。例如:
它会执行不良查询:
上面列出的每一个类通过它们的Parameters属性支持预处理语句,允许应用程序创建一个包含参数占位符的SQL语句,并以可靠且类型安全的方式设定这些占位符的值。如果按正常的方式使用,这种机制就不易受到SQL注入攻击。例如:
它生成的查询等同于:
3.动态代码执行
VBScript函数Eval接受一个包含VBScript表达式的字符串自变量。该函数求出这个表达式的值,并返回结果。如果用户可控制的数据被合并到要计算值的表达式中,那么用户就可以执行任意命令或修改应用程序的逻辑。
函数Execute和ExecuteGlobal接受一个包含ASP代码的字符串,这个ASP代码与直接出现在脚本中的代码的执行方式完全相同。冒号分隔符用于将几个语句连接在一起。如果向Execute函数提交用户可控制的数据,那么攻击者就可以在应用程序中执行任意命令。
4.OS命令执行
下面的API可以各种方式在ASP.NET应用程序中运行外部进程:
System.Diagnostics.Start.Process
System.Diagnostics.Start.ProcessStartInfo
在对对象调用Start之前,可以向静态Process.Start方法提交一个文件名字符串,或者用一个文件名配置Process对象的StartInfo属性。如果文件名字符串可完全由用户控制,那么应用程序几乎可以肯定易于受到任意命令执行攻击。例如,下面的代码将运行Windows calc程序:
然而,如果用户仅能够控制提交给Start的部分字符串,那么应用程序仍然可能易于受到攻击。例如:
API并不解释& 与 | 等 shell元字符,也不接受文件名参数中的命令行参数,因此,如果用户仅控制文件名参数的一部分,这种攻击是唯一能够成功的攻击。
已被启动的进程的命令行参数可以使用ProcessStartInfo类的Arguments属性设定。如果只有 Arguments参数可由用户控制,应用程序仍然易于受到除代码执行以外的其他攻击。例如,如果应用程序以用户可控制的参数作为目标URL执行wget程序,那么攻击者就可以向wget进程提交危险的命令行参数,例如,致使它下载一个文档,并将该文档保存在文件系统中的任何位置。
5.URL重定向
下面的API用于在ASP.NET中发布一个HTTP重定向:
System.Web.HttpResponse.Redirect
System.Web.HttpResponse.Status
System.Web.HttpResponse.StatusCode
System.Web.HttpResponse.AddHeader
System.Web.HttpResponse.AppendHeader
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中还是在应用程序上运行的内部网络内。
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“受保护配置”特性加密这些数据。