脚本侵入概述
从浏览器的角度来看,网页只是一个长字符串。浏览器会按顺序处理这个字符串,在此过程中,会显示某些字符,同时按特殊规则解释其他字符(如 <b> 和 <script>)。如果恶意用户可以将某些特殊字符插入到页中,则浏览器将不知道这些字符不应该处于该位置,将作为页的一部分处理它们。
一个简单化的脚本利用的工作方式如下所示。如果应用程序允许用户发布对最新影片的评论以供其他用户阅读,则利用脚本的步骤可以是:
-
应用程序显示一个用户可以输入评论的窗体。恶意用户编写了一个其中包含 <script> 块的评论。
-
发送窗体,恶意用户的评论将存储在数据库中。
-
另一用户访问该站点。在构造页时,应用程序会从数据库中读取评论并将它们放在页中。恶意用户的 <script> 块将写入页中,就好像它是文本评论一样。
-
当第二个用户的浏览器显示此页时,它将遇到 <script> 块并执行它。
恶意用户还可以使用其他方法来利用脚本。大多数脚本利用都会要求应用程序接受恶意输入,并将其插入到页中(或回显它),浏览器将在该页中执行它。这种利用带来的潜在损害取决于所执行的脚本。它可以是无足轻重的,如在浏览器中弹出的烦人的消息。但是,它也可能会窃取 Cookie、窃取用户输入(如密码),甚至在用户的计算机上运行本机代码(如果对 Internet 安全性的要求不严格),从而造成严重的损害。
有关防止脚本利用的信息,请参见如何:通过对字符串应用 HTML 编码在 Web 应用程序中防止脚本侵入。
SQL 语句利用
有一种脚本利用的变体可以导致恶意 SQL 语句的执行。如果应用程序提示用户输入信息并将用户的输入串联为表示 SQL 语句的字符串,则会出现这种情况。例如,应用程序可能提示输入客户姓名,目的是为了执行类似如下的语句:
"Select * From Customers where CustomerName = " & txtCustomerName.Value
但是,对数据库有所了解的恶意用户可能使用文本框输入包含客户姓名的嵌入式 SQL 语句,产生类似如下的语句:
Select * From Customers Where CustomerName = ‘a‘ Delete From Customers Where CustomerName > ‘‘
执行该查询时,就会危害数据库。
防止脚本利用
防止脚本利用的主要方法就是决不信任来自用户的信息。假定从浏览器发送到您的应用程序的任何数据都包含恶意脚本。
同样,每次将字符串写入页时,您都应该假定字符串可能包含恶意脚本(除非您自己以编程方式创建了字符串)。例如,在从数据库中读取字符串时,您应该假定它们可能包含恶意脚本。安全意识很强的开发人员甚至不信任他们自己的数据库,理由是他们认为恶意用户可能有办法篡改数据库。
ASP.NET 为您提供了几种有助于防止脚本利用的方法:
-
ASP.NET 对查询字符串、窗体变量和 Cookie 值执行请求验证。默认情况下,如果当前的 Request 包含 HTML 编码的元素或某些 HTML 字符(如表示长破折号的 —),则 ASP.NET 页框架将引发一个错误。
-
如果要在应用程序中显示字符串,但不信任这些字符串,可以在响应中回写字符串时将 HTML 编码应用于这些字符串。例如,进行编码后,标记 <b> 将变成 <b>。如果您要显示的字符串来自您尚未确定信任其内容的数据库时,您可能会这样做。
-
如果希望应用程序接受某个 HTML(例如,来自用户的某些格式设置说明),那么,在将这个 HTML 提交给服务器之前,应在客户端对其进行编码。
-
为了防止 SQL 语句利用,决不能串联字符串创建 SQL 查询。相反,使用参数化查询并将用户输入分配给参数对象。有关详细信息,请参见数据适配器命令中的参数。
-
始终对一组预期值执行窗体输入验证以及字符串格式设置/类型验证。例如,如果特定的窗体变量应为整数,则使用 System.Int32.TryParse 方法验证该值是否确实为整数,并使用范围检查帮助确保该值位于可接受范围内。