日期:2014-05-18  浏览次数:21277 次

★用存储过程防止SQL注入是笑话吗?
以前和大家一样,听人说用存储过程+参数能防止SQL注入,听的多了,也就深信不疑,
就算不是绝对的,至少也有很强大的防御力吧。很多人说自从用了参数+存储,不必过滤字符了,腰也不痛了。

今天仔细想了想,在“代码中用变量拼接组合SQL命令”的确危险,有漏洞。
但“存储过程+参数”实质不是一样的吗,虽然传递过程两者有区别,一个是传递组合好的SQL命令字符串,
一个是传递 "存储过程名+参数",不过到了数据库,在存储过程的代码中,最终不是还要将这些参数组合拼接成
一段SQL命令吗?
就好比一个炸弹,一种方法是直接把成品运到某处,另一个是把炸弹的各零件运到某处,某处再拼合,最终还是炸弹

譬如:
string myname="a' or 1=1";
在代码中拼接SQL命令:
mysql="select * from table where name='"+myname+"'";
即mysql= "select * from table where name='a' or 1=1";

如果我们用参数+存储的方式:
@p1="a' or 1=1"  
set @sql="select * from table where name='"+[@p1]+"'" 
exec(@sql)
这样exec(@sql)难道不等效于 exec (select * from table where name='a' or 1=1) 吗? 
如果是,那和在代码中组合SQL命令有何区别?

搜了一下资料,说参数+存储安全性高的大有人在,但认为参数+存储在安全性上并没多大意义的人也不少
,他们认为仍需要进行严格的字符过滤。大家上网搜一下就能看到了。

实在是很困惑,请大家各持己见。谢谢。尽量不要用“可以,因为参数是传值”或"你不了解参数的意义"等空洞的回答,再次感谢。

------解决方案--------------------
你自己实际试验过吗? 用了参数以后,任何特殊字符,比如‘都会转化为普通的字符串,不会再被当成注释符号处理,所以不需要过滤字符。
------解决方案--------------------
据说,SqlParameters这个类在处理参数的时候能自动帮你处理~
据说,使用参数是MSDN推荐的.
------解决方案--------------------
存储过程能免受SQL注入攻击。这是不对,只能阻止某些种类的攻击
存储过程如果使用未筛选的输入,容易受攻击。
使用存储过程,则应使用参数Parameter作为存储过程的输入
测试输入的大小和数据类型,强制执行适当的限制。。 
测试字符串变量的内容,只接受所需的值。 
绝不直接使用用户输入内容来生成 Transact-SQL 语句。 
使用存储过程来验证用户输入。 
在多层环境中,所有数据都应该在验证之后才允许进入可信区域。
实现多层验证。
------解决方案--------------------
修改了楼主的代码,写个示例就知道如何注入:
SQL code
declare @p1 varchar(1000)
declare @sql varchar(1000)
set @p1="a';select 123 -- or 1=1"
set @sql="select * from sysobjects where name='"+@p1+"'"
exec(@sql)
go

------解决方案--------------------
我把代码写的更复杂一点看得更清楚:
SQL code
declare @p1 varchar(1000)
declare @sql varchar(1000)
set @p1="a';select 123 --"
set @sql="select * from sysobjects where name='"+@p1+"' and id=-103"
exec(@sql)
go

------解决方案--------------------
关键是parameter 和存储过程就根本没有关系 不妨写几个注入语句 亲身体验之后就知道了
------解决方案--------------------
LZ这个问题就好比杀毒软件和病毒.目前还没有哪款杀毒软件能真正做到把病毒拘之系统之外.MS几乎每个月都有补丁.但是还是有那么多的攻击/
存储过程+参数不是万能的.但相对于你的拼接SQL是要安全的很多..

------解决方案--------------------
首先 单纯的存储过程根本就不能防SQL注入!
倒是 参数可以过滤SQL注入。
------解决方案--------------------
额,参数也要看什么参数的,楼主说的有一定道理
但是传参不是这么拼凑sql啊

cmd.Parameters.Add("@Tags", System.Data.SqlDbType.NVarChar, 255).Value = xxx;
实际上类似这样的都可以过滤,'被替换成''等等..
不过不要以为这样就安全了 

create proc xxxx
...
 @SearchSQL NText,
....
AS
....

Insert into #IDs(PhotoID) exec(@SearchSQL)


像这种参数,在存储过程中执行sql,可以被注入..不信试试
------解决方案--------------------
恩,参数化查询不应该这么拼接sql
@p1="a' or 1=1"
set @sql="select * from table where name='"+[@p1]+"'" 
exec(@sql)


正确的方法应该是
sql = "select * from table where name=@name"
cmd.Parameters("@name" ........)

如果是用存储过程,应该在存储过程里面执行 select * from table where name=@name
而不是exec(@sql),这样和普通拼接sql没有什么区别

实际应用根据要求来定,比如模糊搜索功能,用LIKE '%words%',这种时候应该进行安全过滤
------解决方案--------------------