以前和大家一样,听人说用存储过程+参数能防止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%',这种时候应该进行安全过滤
------解决方案--------------------------------------------------------