预防SQL注入攻击之我见

数据库
说起防止SQL注入攻击,感觉很郁闷,这么多年了大家一直在讨论,也一直在争论,可是到了现在似乎还是没有定论。

1、 SQL注入攻击的本质:让客户端传递过去的字符串变成SQL语句,而且能够被执行。

2、 每个程序员都必须肩负起防止SQL注入攻击的责任。

说起防止SQL注入攻击,感觉很郁闷,这么多年了大家一直在讨论,也一直在争论,可是到了现在似乎还是没有定论。当不知道注入原理的时候会觉得很神奇,怎么就被注入了呢?会觉得很难预防。但是当知道了注入原理之后预防不就是很简单的事情了吗?

第一次听说SQL注入攻击的时候还是在2004年(好像得知的比较晚),那是还是在写asp呢。在一次写代码的时候,有同事问我,你的这段代码防注入攻击了吗?什么攻击?这是什么呀。

后来到网上各种找,终于弄明白了是怎么攻击进来的了。注入攻击都是来自于客户端,无论是表单提交、URL传值还是Cookie等,其实原理都是一样的。到了服务器端可以分成三种情况:数字、日期时间、字符串。

一、数字。

如何注入?

假设我们要实现一个显示新闻的页面,我们可能会随手写下下面的代码:

  1. string id = Request.QueryString["id"]; 
  2. string sql = "select * from news where ColID=" + id; 

如果传递过来的 id是我们想像的 数字(比如168),那么自然不会有什么问题。但是如果传递过来的id是“168 delete from table ”的话,那么sql的值就变成了“select * from table where ColID=168 delete from news”。对于SQL Server来说是支持一次提交多条SQL语句的,这个为我们提供了方便之余也为SQL注入敞开了大门。显然如果这条SQL语句被执行的话,那么news表里的记录就都没有了。

那么如何预防呢?很简单,因为ColID字段的类型是int的,那么我们只需要验证一下传递过来的id是不是整数就可以了。是整数就不存在注入;如果不是那么就有可能存在注入。即使不存在注入,把一个不是整数的id拼接进去也会造成执行错误。

所以说不管是不是为了预防SQL注入,也都应该验证id是不是整数。

验证方法嘛,可以用TryParse,可以用正则,也可以自己写函数验证。但是不建议用try异常的方式,因为这个有效率问题。

这里还有一个特殊情况,就是对于批量删除这类的会传递过来多个数字,比如“1,2,3,10”,这个也需要验证一下,万一有人利用这个漏洞呢。至于验证方法也很简单,自己写个函数就ok了。

二、日期时间

这个和数字的情况是一样的,验证是不是日期时间即可。

三、字符串

最麻烦、争议最大的就是这个了。

先看一下如何注入

比如我们先要按照新闻标题来进行查询,可能写的代码:

  1. string key = txtTitle.Text; 
  2. string sql = "select * from news where title like '%" + key + "%'"

这个又是如何注入的呢?我想先问大家一个问题:如果key的值永远都不会包含单引号,那么会不会被注入进来?

那么用了单引号又是如何注入的呢?假设key=" ' delete from news --" ,那么sql的值就是“ select * from news where title like '%' delete from news -- ' ”。

先用一个单引号和前面的单引号组成一对封闭的单引号,这一对单引号内部('%')就作为字符串处理,而外面的就被作为SQL语句处理,而第二个单引号被 “--”给注释掉了,这样就保证了整个sql语句的正确性。

这是注入的一种方法。

那么如何来防止呢?想想刚才的问题,如果没有单引号是不是就天下太平了呢?对于这种情况(前面的“数字”的情况不算),到目前为止我是没发现不用单引号,还能够注入进来的方法。也许是我孤陋寡闻吧,不知道各位高手是否知道对于这种情况,不用单引号还能注入进来的方法。

既然找到了罪魁祸首,那么就好办了,把单引号干掉就ok了。key = key.Replace("'", "''");这时候sql的值就是” select * from news where title like '%'' delete from news --'”。

对于SQL 来说在一对单引号内部的两个单引号表示一个字符串形式的单引号。这样我们就把罪魁祸首改造成了字符串了。在一对单引号内的“--”也是普通的字符串而不代表注释。

罪魁祸首是单引号,想不明白为什么有许多人都去过滤 “delete、update”这一类的关键字,他们都是安善良民呀,他们是很冤枉的。当然了,如果前提是程序都已经写好了,不能修改内部代码,那就另当别论了。至于“--”顶多算是帮凶,如果您不放心的话,把他处理了也行。

总结:数字、日期时间的,验证类型;字符串的,处理好单引号。

另外为了安全起见,不要用sa连接数据库,xp_cmdshell这一类的有危险的扩展存储过程也应该处理一下(比如删除)。

ps:添加修改数据的时候可以用参数化的SQL语句,但是目的不是防止注入,而是重用执行计划。

还有就是js脚本的问题,这个还没有仔细考虑,可以用html编码的方式,也可以用替换的方式,还有ubb的漏洞等。

原文链接:http://www.cnblogs.com/jyk/archive/2009/11/26/1610987.html

【编辑推荐】

  1. NoSQL数据库渐入佳境 国内应用案例盘点
  2. 记一次成功的SQL注入入侵检测附带SQL性能优化
  3. 数据库迁移之何去何从
  4. 教你五步优化你的MongoDB
  5. 数据库缓存重建不容忽视
责任编辑:艾婧 来源: 金色海洋工作室
相关推荐

2009-09-23 10:43:22

2010-09-14 16:28:52

2014-11-04 13:43:10

2019-02-22 09:00:00

2009-02-04 16:51:48

2020-08-07 08:13:08

SQL攻击模式

2010-09-14 16:00:16

2012-11-08 17:02:58

2021-01-11 09:52:03

JavaSQL框架

2009-03-10 08:05:19

2010-09-16 21:20:02

2010-09-08 13:31:24

2012-04-12 15:06:44

2013-04-26 11:26:00

2010-09-30 12:53:10

2022-02-14 17:13:46

攻击面管理网络安全

2011-07-12 10:38:10

2010-03-12 11:08:51

2011-04-01 09:42:58

2010-09-20 11:22:08

点赞
收藏

51CTO技术栈公众号