日期:2014-05-17  浏览次数:20572 次

参数化SQL能防止注入的原理
如题,很多人认为参数化就是‘’自动过滤‘’,我认为不对,大家讲讲看原理是什么。

------解决方案--------------------
请参考 http://www.cnblogs.com/LoveJenny/archive/2013/01/15/2860553.html
------解决方案--------------------
参数化也不能完全解决 sql注入问题,还是建议你使用其他的,比如 正则表达式等过滤特殊字符:

如何防止sql注入 
http://www.blogjava.net/GavinMiao/archive/2011/08/24/357182.html
------解决方案--------------------
攻击永远比防御强,而且不存在没有漏洞的系统,“完全”防止是不可能的,只能说把现有出现过和能预估的风险降低而已
------解决方案--------------------
补充一点上贴,
实际注入中,并不是我上面写的那么简单,因为一般情况,你不知道别人的库结构是如何的,
这时候其实要靠注入经验、猜测、还要看当前的数据库帐号权限有多大等等。
当然, 即便当前帐号只有对业务表的操作权 不能威胁到服务器,那么你想想, 一条update 金额已经有足够大的损失了。


最直观的反例是sql_excutesql里面还在拼SQL,这个是最容易表述也是最简单的,   这样的方式就完全没有用。 这个告诉我们, 不要以为别人说怎么样就可以怎么样了, 你懂了原理,就知道这些东西不能道听途说。 区分真伪的能力在于你掌握了多少。


create proc p
(@id int,
@name varchar(10))
as
begin
 execute('select * from tb where id=' + @id + ' and name=''' + @name + ''')
end
go


在c#里,调用这个存储过程,给了两个参数,一个@id,一个@name
是的,@name,@id被定义了类型, @name里的字串被进行了转义, 乍一看没问题, 事实呢? 只是构造相对再复杂一点而已, 只要你脑子够清楚不被'和''搞晕, 一样的。

sqlparamepter pm = ....

pm[0].value=1;
pm[1].value="a'";

那么在execute里执行里面拼的语句已经是
select * from tb where id=1 and name=''a'''
你会说这条语句报错,因为定界符不匹配,
对的,你说对了, 为什么定界符不匹配,因为构造非法的字符串造成了定界符不匹配,既然已经干扰了定界符, 能过合理构造,你就能构造出你想要的语句。
这么说应该能说明吧, 不用我再构造清一次你的admins表吧。


这些是最直观的例子。


你会说,你通过避免拼动态语句来解决这个问题, 对的,可以解决。

但是会有更高阶的东西, 利用本身操作系统或者数据库服务器的一些漏洞(一般是较低层的,比如某某溢出),通过SQL注入,结合一些方法,完成攻破。 这个就不光是纯SQL的注入了,就不多介绍了。

9年前对这些东西感兴趣,弄过一些,包括国内知名的两个商业论坛, 后来淡了,这些东西没有再过多了解, 但是原理是不变的。

随手敲的,可能手误,见谅。