技术开发 频道

在C#3.0中使用LINQ轻松防御SQL注入攻击



二、SQL注入攻击剖析


   
在本节中将给出个简单的SQL注入的例子,通过这个例子读者可以了解了这个错误是多么容易犯,并且这些注入错误使用一些设计技巧和编程规范就可以很容易地避免。

   
在这个例子中,Web应用程序包含了一个简单的customer数据查询页SQLInjection.aspx。这个页布在一个非常易受SQL注入攻击的隐患。这个页包含了一个CompanyName输入服务端控件和一个数据网格控件,用来演示从微软的例子数据库Northwind查出来的结果(在本例中将使用微软SQL Server2005作为我们的演示数据库)。这个查询在执行时包含了一个非常普遍应用程序设计错误,也就是它根据用户的输入动态地建立一个SQL查询语句。这种方式对于Web应用程序访问数据库是非常不好的习惯。这是因为这样做必须有一个前提,就是使用这个Web程序的用户是可信赖的,如果用户怀有恶意,那将是非常危险的。下面是Search按钮中的生成SQL语句的代码:

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; }
在这种情况下,如果一个用户输入"Oracle"作为公司名,并单击Search按钮,这样将在浏览器中显示显示和公司相符的正确的结果。但一个攻击者也可以很容易地控制动态查询语句的生成,如,通过插入UNION子句和并通过SQL的注释符号(--)来终止其余的语句。换句话说,就是使用以下的输入来代替"Oracle"作为公司名:

Oracle' UNION SELECT CustomerID, ShipName, ShipAddress
   FROM ORDERS--

   
上面SQL表达式在服务端的执行结果是向SQL语句中插入了一条恶意的请求命令。如果将其翻译成动态的SQL语句的话,代码如下:


SELECT [CustomerID], [CompanyName], [ContactName] FROM [Customers] WHERE CompanyName ='Oracle' UNION SELECT CustomerID, ShipName, ShipAddress FROM ORDERS--'
    上面所得到的SQL语句的语法完全正确,它将返回Customer表中Oracle的数据,同时也返回了Orders表中所有的数据。显示结果如图1如示:



   图一个成功的SQL注入的显示结果。它通过在命令行后加入非法的命令来获取数据库中敏感的信息。
1
相关文章