参数是否足以防止Sql注入?
我一直在向我的同事们讲述如何在SQL查询中使用参数,特别是在.NET应用程序中。 我甚至已经承诺给予他们免于SQL注入攻击。
但是我开始怀疑这是否属实。 是否有任何已知的SQL注入攻击将成功参数化查询? 你可以例如发送一个string,导致服务器上的缓冲区溢出?
当然还有其他一些考虑要确保一个Web应用程序是安全的(比如清理用户input和所有这些东西),但现在我正在考虑SQL注入。 我特别感兴趣的是对MsSQL 2005和2008的攻击,因为它们是我的主数据库,但是所有的数据库都很有趣。
编辑:澄清我的意思是参数和参数化查询。 通过使用参数我的意思是使用“variables”,而不是build立一个string的SQL查询。
所以不要这样做:
SELECT * FROM Table WHERE Name = 'a name'
我们这样做:
SELECT * FROM Table WHERE Name = @Name
然后在查询/命令对象上设置@Name参数的值。
占位符足以防止注射。 您可能仍然对缓冲区溢出持开放态度,但这是与SQL注入完全不同的攻击风格(攻击向量不是SQL语法,而是二进制)。 由于传递的参数都将被正确转义,因此攻击者无法传递将被视为“实时”SQL的数据。
您不能在占位符内使用函数,也不能使用占位符作为列名或表名,因为它们被转义并引用为string文字。
但是,如果在dynamic查询中使用参数作为string连接的一部分,则仍然容易被注入,因为string不会被转义,而是字面上的。 使用其他types的参数(如整数)是安全的。
也就是说,如果您使用use input来设置security_level
之类的值,那么有人可以让自己成为系统中的pipe理员,并且拥有一个free-for-all。 但是这只是基本的inputvalidation,并没有与SQL注入。
不,每次将未validation的数据插入到SQL查询中时,仍然存在SQL注入的风险。
通过从SQL语法中分离字面值,查询参数有助于避免此风险。
'SELECT * FROM mytable WHERE colname = ?'
这很好,但还有其他一些目的是将数据插入到不能使用查询参数的dynamicSQL查询中,因为它不是SQL值,而是表名,列名称,expression式或其他语法。
'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')' ' ORDER BY ' + @colname'
无论您是使用存储过程还是直接从应用程序代码执行dynamicSQL查询都无关紧要。 风险依然存在。
这些情况下的补救措施是根据需要聘请FIEO :
-
filterinput:在插入数据之前validation数据看起来像合法的整数,表名,列名等。
-
转义输出:在这种情况下,“输出”是指将数据放入SQL查询中。 我们使用函数来转换在SQLexpression式中用作string文字的variables,以便string中的引号和其他特殊字符被转义。 我们还应该使用函数来转换将用作表名,列名等的variables。对于其他语法,例如dynamic地写入整个SQLexpression式,这是一个更复杂的问题。
在这个线程中似乎有一些关于“参数化查询”的定义的混淆。
- SQL,如接受参数的存储过程。
- 使用DBMS参数集合调用的SQL。
鉴于以前的定义,许多链接显示工作攻击。
但“正常”的定义是后者。 鉴于这个定义,我不知道任何SQL注入攻击,将工作。 这并不意味着没有一个,但我还没有看到它。
从评论中,我没有足够清楚地expression自己,所以这里有一个希望更清楚的例子:
这种方法对SQL注入是开放的
exec dbo.MyStoredProc 'DodgyText'
这种方法不适用于SQL注入
using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar); newParam.Value = "DodgyText"; ..... cmd.Parameters.Add(newParam); ..... cmd.ExecuteNonQuery(); }
符文 –
这是一篇过时的文章,但仍然有效:
SQL注入 – 参数化查询是否安全?
任何用于构造dynamic查询的stringtypes(varchar,nvarchar等)的sql参数仍然是脆弱的
否则参数types转换(例如int,decimal,date等)应该消除通过参数注入sql的任何尝试
编辑:一个例子,其中参数@ p1旨在成为一个表名称
create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) AS SET NOCOUNT ON declare @sql varchar(512) set @sql = 'select * from ' + @p1 exec(@sql) GO
如果从下拉列表中select@ p1,则这是一个潜在的sql注入攻击vector;
如果@ p1是以编程方式编写而没有用户介入的能力,那么它不是一个潜在的sql注入攻击vector
缓冲区溢出不是SQL注入。
参数化查询确保您可以安全地防止SQL注入。 他们并不保证你的SQL服务器中没有可能的漏洞,但是没有什么能保证这一点。
你的数据是不安全的,如果你使用任何forms的dynamicSQLforms或forms,因为权限必须在表级别。 是的,您已经限制了特定查询的注入攻击的types和数量,但不限制用户如果find进入系统的方式可以获得的访问权限,并且完全可以让内部用户访问他们不应该访问的内容为了欺诈或窃取个人信息而出售。 任何types的dynamicSQL都是危险的做法。 如果你使用非dynamic存储特效,你可以在processesdure级别设置权限,除了proc定义的内容(当然除了系统pipe理员),用户不能做任何事情。
存储过程可能容易受到溢出/截断的特殊types的SQL注入攻击,请参阅:通过数据截断在此处启用注入:
只要记住,使用参数你可以很容易地存储string,或者说如果你没有任何政策的用户名,“);删除表用户; – ”
这本身不会造成任何伤害,但是你最好知道在你的应用程序中进一步使用这个date的地方和方式(例如存储在一个cookie中,稍后检索来做其他的事情。
我刚刚第一次遇到SQL注入攻击。 这是一个痛苦,但要清理,所以没有这样的事情太多的安全性,如果它不干扰function。 我相信附件通过一个存储过程,并想知道是否有任何人的盒子解决scheme来清理数据进入存储过程paramater?
请阅读Plamen Ratchev撰写的以下伟大的文章:
您可以运行dynamicSQL为例
DECLARE @SQL NVARCHAR(4000); DECLARE @ParameterDefinition NVARCHAR(4000); SELECT @ParameterDefinition = '@date varchar(10)' SET @SQL='Select CAST(@date AS DATETIME) Date' EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'