在开发人员承受越来越多的安全责任之时,许多开发人员了解到的第一个Web 应用安全漏洞,是一个被称为“SQL注入”的极危险的命令注入形式 。命令注入的原始的形式本是指这样一种漏洞:攻击者通过提供一个正常使用者 意料之外的输入,改变你的Web应用程序的运行方式,从而允许攻击者运行服务 器上的非授权的命令。无疑,SQL注入式攻击是很常见的、被广泛使用的攻击形 式。幸运的是,一旦我们理解了这个问题,就可以很容易地防止SQL注入式攻击 。更妙的是,现在微软的数据访问技术向.net开发人员提供了彻底地清除SQL注 入漏洞的机会,当然前提是能够正确使用。这种技术称为“语言级集成查 询”(Language Integrated Query (LINQ)),并随Visual Studio "Orcas" 和 .NET Framework 3.5一起发布。本文将讨论如何通过 LINQ强化Web应用程序的数据访问代码,从而解决通过SQL注入进行攻击的问题。
SQL注入是一种Web应用程序的安全漏洞,通过它攻击者可以将恶意数据 提交给应用程序,欺骗应用程序在服务器上执行恶意的SQL命令。理论上讲,这 种攻击是容易预防的,不过由于其允许攻击者直接运行针对用户关键数据的数据库命令,从而成为一种常见的、危害性大的攻击形式。在非常极端的情况下,攻 击者不但能够自由地控制用户的数据,还可以删除数据表和数据库,甚至控制整 个数据库服务器。
如果这种攻击容易预防,那么为什么还如此危险呢? 首先,由于众所周知的经济上的原因,你的应用数据库是非常诱人的,可以引起 攻击者的极大注意。如果SQL注入漏洞在Web应用程序中可能存在着,那么对于一 个攻击者来说是很容易检测到的,然后就可以利用它。很显然,即使SQL注入错 误并不是开发人员最经常犯的错误,它们也很容易被发现和利用。
对SQL 注入的剖析
这里我们给出一个SQL注入的例子来说明两个问题,一是SQL 注入这种错误是很容易犯的,二是只要进行严格的程序设计,这种错误是很容易 预防的。
这个示例用的Web应用程序包含一个名为SQLInjection.aspx简 单的客户搜索页面,这个页面易于受到SQL注入攻击。此页面包含一个 CompanyName的输入服务器控件,还有一个数据表格控件,用于显示从微软的示 例数据库Northwind的搜索结果(这个数据库可从SQL Server 2005中找到)。在 搜索期间执行的这个查询包含一个应用程序设计中很普通的错误:它动态地从用 户提供的输入中生成查询。这是Web应用程序数据访问中的一个主要的错误,因 为这样实际上潜在地相信了用户输入,并直接将其发送给你的服务器。在从 “搜索”的单击事件启动时,这个查询看起来是这个样子:
protected void btnSearch_Click(object sender, EventArgs e)
{ String cmd = "SELECT [CustomerID], [CompanyName], [ContactName]
FROM [Customers] WHERE CompanyName ='" + txtCompanyName.Text
+ "'";
SqlDataSource1.SelectCommand = cmd;
GridView1.Visible = true;
}
在这种情况下,如果一个用户输入“Ernst Handel”作为公司名,并单击“搜索”按钮,作为响应屏幕会 向用户显示那个公司的记录,这正是我们所期望的理想情况。不过一个攻击者可 以轻易地操纵这个动态查询。例如,攻击者通过插入一个UNION子句,并用一个 注释符号终止这个语句的剩余部分。换句话说,攻击者不是输入“Ernst Handel”,而是输入如下的内容:
Ernst Handel' UNION SELECT CustomerID, ShipName, ShipAddress
FROM ORDERS--
其结果是这个SQL语句在服务器端执行,由于添加了这个恶意的请求 。它会将这个动态的SQL查询转换为下面的样子:
SELECT [CustomerID], [CompanyName],
[ContactName]
FROM [Customers]
WHERE CompanyName ='Ernst Handel'
UNION SELECT CustomerID, ShipName,
ShipAddress
FROM ORDERS-- '
这是一个相当合法的SQL语句,它可以在应用程序数据库上执行 ,返回order表中所有的客户,这些客户通过应用程序已经处理了定单。