SQL injection可以说是一种漏洞,也可以说成是一种攻击方法,程序中的变量处理不当,对用户提交的数据过滤不足,都可能产生这个漏洞,而攻击原理就是利用用户提交或可修改的数据,把想要的SQL语句插入到系统实际SQL语句中,轻则获得敏感的信息,重则控制服务器。SQL injection并不紧紧局限在Mssql数据库中,Access、Mysql、Oracle、Sybase都可以进行SQL injection攻击。
一、SQL Injection的原理 SQL Injection的实现方法和破坏作用有很多,但万变不离其宗,其原理可以概括为一句话 :SQL Injection就是向服务器端提交事先准备好的数据,拼凑出攻击者想要的SQL语句,以改变数据库操作执行计划。这句话主要包含这么三层意思:
注:这里只是简单的列出SQL 注入的方式,展开来说明可参看SQL Injection的源由與防範之道,駭客的 SQL填空遊戲(上) ,駭客的 SQL填空遊戲(下)
二、ASP.NET应用程序如何避免SQL Injection攻击
发生SQL Injection攻击的根源是SQL语句的拼凑方式,如果是通过直接拼接SQL的方式就非常容易发生SQL Injection攻击,SQL Server的SQL语句拼凑还有另一种更加安全的方式:参数查询。如果用户需要创建每次使用不同值的查询,则可以在查询中使用参数。那么这个参数到底是什么呢?其实确切的说,应该把这个参数叫做占位符。即参数是在运行查询时提供值的占位符。在SQLServer数据库中,在需要显示的内容(Select子句)与查询条件(Where子句)中都可以采用参数,从其他地方接收输入的值。不过大部分情况下,都只在查询条件中使用参数。即在单个行或者组的搜索条件中使用参数作为占位符。
在SQLServer中,参数可以分为两种,即未命名参数与命名参数。通常情况下,如果SQL语句中只需要一个参数的话,那么可以采用未命名参数。如需要查询某个员工上班到现在的全部出勤信息。此时就只需要用到员工编号这个参数即可。此时可以采用未命名的参数。不过有的时候可能查询时需要不止一个参数。如现在需要查询某个员工在4月份的出勤情况。此时就需要两个参数,分别为员工编号、月份。或者需要三个参数,分别为员工编号、开始日期、结束日期等等。总之要多于一个参数。此时就需要使用命名参数。因为如果使用未命名参数的话,则数据库并不知道要把哪个参数对应到哪个地方。所以说,如果要在查询中使用多个参数,那么此时命名参数就会非常有用。
SqlCommand代表了在SQL Server 数据库中执行的SQL或者存储过程,它有一个属性是Parameters 包含了SQL 语句中用到的参数集合,对于SQL命令中要用到的每一个参数都对应一个SqlParameter对象。添加SqlParameter对象到Parameters集合有两个方法:Add()和AddWithValue()。他们都有多个重载方法,Add()有一系列的重载方法,我一般是使用方法Add(String, SqlDbType),然后单独赋值。
ADO.NET的参数查询到达SQL Server数据库的时候是通过系统存储过程sp_executesql执行的:
exec sp_executesql N'Select * From Products Where ProductID = @ProductID',N'@ProductID int',@ProductID=13
上述查询上包含了参数的数据类型和参数值,传入的值是字符串只是代表了一个文本,而不会成为SQL的一部分,这样就避免了SQL Injection。
通过使用参数查询还有另一个好处是可以提高SQL 的性能,当 SQL Server 会看到 SQL 语句时,它首先检查其缓存中是否存在一个完全相同的语句。 如果找到了一个,它将执行优化的执行计划,以确保尽可能有效地执行该语句。如果它找不到完全匹配,它通过创建一个缓存,在执行语句中使用该执行计划。 您可以看到 sp_executesql 调用的第一部分包含该语句,和它始终都是一样。它的所有后续使用将使用缓存优化的计划。 如果此语句动态生成使用字符串串联,并且在 ProductID 更改的时候,需要创建并为每个值的 ProductID 存储执行计划。 "....WHERE ProductID = 13"与"....WHERE ProductID = 96"不一样。
三、微软发布的3款SQL Injection攻击检测工具
随着 SQL INJECTION 攻击的明显增多,微软发布了三个免费工具,帮助网站管理员和检测存在的风险并对可能的攻击进行拦截。