关于防止sql注入的几种手段(三)

上一篇引起不少争议,也是自己没有一次性写完。

上回说到邹健大哥的存储过程有漏洞, 有人又提出这个很多都是程序员加上去的,压根就不可能注入,的确,有很多拼凑sql的时候是程序里面加上去的,不是来自外界的“直接”输入。我上次的演示例子是基于的最后的排序,那如果要是在where 条件里面呢?能保证100%都不是来自外界的输入吗?另外,软件的分层开发,很多程序员的水平参差不齐,能保证where条件都能100%保证过滤了外界的邪恶输入吗?还有,能保证过滤100%能抵挡黑客的攻击吗?

 

这样,我们再来看看园子里的人 是如何防止注入攻击的,在gg搜索框输入: site:cnblogs.com 防止sql注入 

2750条记录, 第一篇是http://www.cnblogs.com/flyfish/archive/2006/04/26/386049.html,文中只讲了原则,没有实施手段。提到的asp.net安全缺陷解决,在客户端使用服务器验证控件验证,这个是绝对不可靠的,客户端验证是为的用户体验,黑客是不会在浏览器框里输入的。所有的验证都必须要在服务器端再次验证。

 

排名第二位的是http://www.cnblogs.com/killkill/archive/2009/02/26/1398524.html,kill朋友的,有具体的实施手段,防止sql注入的策略,一眼看去那个过滤,就知道有个地方没有注意到,xp_cmdshell命令没有过滤。肯定是有漏洞,当然你可以保证你的系统里面扩展存储过程是默认关闭的,但是你不能保证其他阅读了你文章的用户基于某些原因开启了扩展存储过程。废话一下,强烈建议不要开启扩展存储过程,如果要使用,看clr proc能不能满足你的需求, 不过开启clr也是需要数据库付出一定的代价的,数据库不是很繁忙,可以开启。

 

排名第三位的是转载自csdn的, http://www.cnblogs.com/zhuawang/archive/2008/04/26/1172407.html

也是基于的过滤。

 

    基于过滤的方法不是不行,不是达不到效果,而是基于过滤你不能保证你过滤完所有的危险,如果你认为你过滤完所有的危险,你觉得用户会很方便吗?就像我现在写的文章一样,如果博客园使用过滤,那我这篇文章能被发表吗?所以基于过滤貌似是行不通的,但是有些时候如果全都是参数化,存储过程又太过于复杂,那些不经常写存储过程的程序员很是头疼,怎么办呢?

 

 总结我自己的开发经验来说,没有任何绝对的,只有结合具体情况具体考虑。

 1 检查,类型检查,如果是int一定要tryparse,如果是有限的几个值,一定要枚举匹配。如果是日期一定要转成日期转入数据层。

2 长度,长度是个非常重要的因素,比如登录,如果用户名是严格限死的10个字符以内就10个字符以内,用户名中间没有空格就检查不能有空格,但是这个长度因素是需要严格控制的,不能把长度放开到10个字符以上,因为 "truncate table s"和这个"drop table s",长度需要跟具体需求具体确定,不能全部一刀切。如果有哪位可以在10个字符以内注入成功的,还请告之,我赶紧改我的程序了,呵呵。

3 过滤检查,如果压根不可能出现xp_的地方一定要过滤,至于其他的, delete,drop,很多地方都不能确保

如果前两个检查不能排除危险的话到第三步过滤建议还是都是用存储过程参数化(或语句参数化),因为到第三步的时候已经不能确保100%防止注入了。

还有的时候,经常被群里的人或朋友问到如果我要传递多个ID进去,比如批量删除,有什么办法,网上的解决办法很多,我就不一一说了,主要有在存储过程里字符串拆分组成临时表,或者使用邹健大哥的使用func,配合apply。这些都很复杂,实现起来需要很强的sql根底,不过我的实现就是确保提交过的字符串只有数字和半角逗号组成即可。这样就能确保没有注入可能,然后使用拼凑sql的方式+语句参数化其他where条件来确保安全。

 

其实在这几年我自己的开发历程中,我自己总结我自己对sql注入的安全性认识,经历了几个认识阶段和惨痛教训。

1最初的不知道什么叫sql注入

2使用过滤危险关键字来防止注入

3使用参数化存储过程

4有些地方需要使用sp_executesql

5见招拆招,根据具体的情况做具体的防注入策略,减少程序开发复杂度

 

 如果我的方式仍然有漏洞,还请各位指出,大家把这个安全完善了,那些初级黑客也就不至于那么嚣张了。(sql注入手段的确很低级)

这系列文章中涉及几位博友文章, 还请见谅,只是指出安全性问题,如果我有,也请大家指出。

 

 可能我的表述不是很清楚,应该是在不方便参数化,参数化会导致开发复杂,开发效率慢的情况下,使用拼凑sql,如何来防止注入,意图是强调在使用拼凑sql时,对于外来输入长度,和类型的检查,而不是互联网文章里讲述的强调对输入的过滤。过滤是不靠谱的,只有长度和类型,才能很好的拼凑sql时的注入。

 

posted on 2009-11-25 10:29  Keep Walking  阅读(6249)  评论(25编辑  收藏  举报