事情是这样子的,公司网站突然有一天被sql注入了,然后老板就要求加强以前做的sql防注入功能,就是类似每次get、post 请求都要对参数进行检查(类似继承IHttpModule的那种)。
重点来了,现在实现的效果是,每一次页面访问,点击按钮触发的事件(按钮触发的事件post请求,请求体中有这样的参数,btnSet=XXXX&txtName=Tom),都会对参数进行检查,不能含有update、set、delete、exec、where、单引号…………等的关键字。导致出现一个问题,一个页面的Button含有set关键字也被过滤掉了,导致执行报错。
请问这种方法可靠吗??
可靠,只要你能把所有情况都考虑到。不过你这种直接就执行SQL的做法,还是不太好。
我没有直接执行sql语句啊,那些敏感词目的是防止别人在HTTP请求中做手脚的,公司的架构还是三层。
@蛊惑的我: 如果你没有直接执行SQL的话,你为什么需要在HTTP请求中去过滤SQL的关键字呢?
@Launcher: 老板说,防止别人使用Fiddler之类的软件,在HTTP对请求参数进行伪造,进行sql注入。。
@蛊惑的我: 你再仔细思考下你的流程,就算我用什么 Fiddler 的构造个 string cmdText = delete * from table1 语句,你的页面或者 Handler 也收到了此语句,请问,你的代码中有这样代码吗:
SqlCommand cmd = new SqlCommand();
cmd.CommandText = cmdText;
cmd.ExecuteNoQuery();
@Launcher:
直接执行肯定是没有的,但应该可以这样子吧,txtName=tom' delete * from table --
还有,我打个比方,我用DropDownList,里面的值都是预先写死的,那我还有必要对DropDownList的值进行sql敏感词过滤吗??也就是说,黑客有可能在HTTP请求过程中,利用Fiddler之类的软件对DropDownList的selectvalue 做手脚吗?
@蛊惑的我: 我假设:txtName=tom' delete * from table ,那么如果你采用拼接SQL的方式,那么能否被注入,就看你拼接出来的SQL语句是否能正确执行;如果你采用参数化查询,有注入风险的参数就会被阻止。
光看别人说没有用,你自己简单的做个测试就行了。
@Launcher:
发现跟你谈得变方向了,我知道参数化能阻止sql注入!
@蛊惑的我: 知道的话,那你就知道没必要对你的请求做SQL注入检查。
@Launcher:
但是很不幸,公司历史问题选择了动软代码生成器,where之后的条件都是拼接出来的。可能动软也觉得where之后的字段不确定,所以就没做参数化,直接就拼接了。
@蛊惑的我: 很不幸,我在前面的回答中已经三番五次的问你是否有直接执行SQL语句的代码,你一直回答没有,但是现在你又突然说有了,那么请你检查你的参数的值,以确定是否有注入风险,推荐的方式是在每个方法中去根据特定的参数的业务含义来检查它是否是具有正确的值。
你老板不懂...就算你的button text是"delete from users"又如何?难道你会去获取button text然后作为sql执行么. 你只要保证你执行的sql中用到的参数(可能是外界传来的)都检查过就可以了。
是的,我打个比方,我用DropDownList,里面的值都是预先写死的,那我还有必要对DropDownList的值进行sql敏感词过滤吗??也就是说,黑客有可能在HTTP请求过程中,利用Fiddler之类的软件对DropDownList的selectvalue 做手脚吗?
@蛊惑的我: 当然可能,所以你要做到“永远不要信任前台传过来的数据”(即使是你自己js程序传来的,这太容易改了)。前端验证只是为了用户友好(比如用户输错了东西可以立刻知道,而不是点了提交到服务器然后才报错),但是前端验证不可靠,服务器端肯定还是要做检查的。
@蛊惑的我: http module处理每一个参数就没必要了,蛋疼,降低效率。你只要在每个接口里做检查就可以了。
@水牛刀刀:
那你们通常是做怎样的一个后台验证架构?对HTTP请求过来的参数进行判断(无论是get的URL参数还是post过来的表单参数)也是使用继承IHTTPModule的这种方法吗?还是每个页面都使用公共验证类库?
@蛊惑的我: 你还是拿你的某个接口举例让我来讲吧,没有场景很难跟你解释。
如果是param方式的话不存在这种问题,如果是拼接SQL的方式,只需要把单引号替换成两个单引号即可
是的,使用动软代码生成器where之后的条件都是拼接的,而且之前开发人员水平参差不齐,很多页面都没判断,所以就用了类似继承IHttpModule接口的管线过滤,在每次请求(无论get or post)都对HTTP提交过来的参数进行判断。我就是不知道,如果是DropDownList之类的selectvalue(值预先写死的),还需要判断吗?
@蛊惑的我:
当然需要,因为可以模拟数据直接提交,也就是客户端的信息是不可靠的,一定要在服务端做处理
两层措施:
1、第一层,过滤措施,你在IHttpModule中过滤也好还是在调用指定方法中过滤也好,这种过滤都不应该移除对应的关键字吧(因为如博客园的博文,不能把博文中的关键字移除一样),这层更重要的是在于检查,根据你的逻辑给予适当提示非法字符,或则用参数化保存到数据库中。
2、第二层,参数化查询,你的所有sql语句要么参数化,要么存储过程,要么sql_executed来执行,即不会有办法sql注入啊。只是这层是到了执行的最后环节,你可以根据过滤措施来提前终止你的代码提高效率。而参数化sql却是必不可少的。
另外还请参看:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html
看了下上面的留言,貌似LZ是没有参数化查询,直接进行SQL拼接,然后使用关键字替代法来防止SQL注入。不知道这样总结对么
关键字替代法不是很可靠,注入的关键字很多,防不胜防,建议早日改为参数化查询。实在太大无法修改的话,网上有现成的关键字屏蔽列表的,可以搜索
这种方法应该可靠吧
无语.每次请求就执行检查.而且带来不必要的麻烦,如果含这些关键字我岂不能提交请求了.
在数据库操作时,还是采用转义符替代.
是的。老板的意思就是这样!