随笔 - 103  文章 - 2 评论 - 919 trackbacks - 21
<2008年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789


转载请保留链接。
国际管理VS中国国情链接 8-21 13:48

与我联系

搜索

 

常用链接

留言簿(12)

我参与的团队

我的标签

随笔分类

随笔档案

文章分类

相册

最新随笔

积分与排名

  • 积分 - 146208
  • 排名 - 249

最新评论

阅读排行榜

评论排行榜

60天内阅读排行

google中搜索“分页存储过程”会出来好多结果,是大家常用的分页存储过程,今天我却要说它是有漏洞的,而且漏洞无法通过修改存储过程进行补救,如果你觉得我错了,请读下去也许你会改变看法。

 

通常大家都会认为存储过程可以避免sql注入的漏洞,这适用于一般的存储过程,而对于通用分页存储过程是不适合的,请看下面的代码和分析!

 

一般的通用的分页存储过程代码如下:

 

通用分页存储过程

 

大家可以看到上面的存储过程中是通过一些步骤最终拼接成一个sql字符串,然后通过exec执行这个串得到分页的结果。

 

我们假定要做一个这样的查询,通过用户名UserName模糊查询用户,为了叙述方便,便于理解我们只考虑取第一页的情况,取出存储过程中取第一页的拼串行如下:

set @strSQL = 'SELECT TOP ' + str(@PageSize+ ' ' + @strGetFields + ' from [' + @tblName + ']  where ' + @strWhere + ' ' + @strOrder

 

为了便于说明问题,我们可以假定@pageSize20@strGetFields ‘*’@tblNameUserAccount,@strOrder’ ORDER  BY  ID DESC’ 那么上面一行可以写成如下形式:

set @strSQL = 'SELECT TOP 20 *  from [UserAccount]  where ' + @strWhere  + ' ORDER BY ID DESC’

 

我们可以假定用户输入的模糊用户名是: Jim’s dog

我们用SqlParameter传递参数给分页存储过程@strWhere 的值是:’UserName LIKE ‘’%Jim’’ dog%’’’(注意LIKE后边的字符串中的单引号已经全部变成两个单引号了),我们将这个值代入上面的@strSQL赋值语句中,如下:

 

set @strSQL = 'SELECT TOP 20 *  from [UserAccount]  where  UserName LIKE ''%Jim'' dog%'' ORDER BY ID DESC’

 

让我们写上声明变量的部分执行在查询分析器中测试一下,代码如下:

 

DECLARE @strSQL varchar(8000)
DECLARE @strWhere varchar(1000)
SET @strWhere = 'UserName LIKE ''%Jim'' dog%'''
set @strSQL = 'SELECT TOP 20 *  from [UserAccount]  where ' + @strWhere + ' ORDER BY ID DESC'
print @strSQL
exec (@strSQL)


大家可以把上面几行代码粘贴到查询分析器中执行一下,就可以看到下面的画面:


在消息的第一行,打印出了要执行的sql语句,很显然此语句的 LIKE ‘%Jim’ 后面的部分全部被截断了,也就是说如果用户输入的不是Jim’s dog而是Jim’ delete from UserAccount那么会正确的执行删除操作,传说中的sql注入就会出现了。

 

问题出现了,我们应该怎么解决问题?

1.  很显然我们使用SqlParameter传递参数已经将单引号替换成了连个单引号了,可是因为我们在数据库中拼串导致替换并不能解决问题。

2.  根据我的实验证明如果使用存储过程不可能解决这个问题,我们只有将这个存储过程要执行的拼串操作放到数据访问层去做,才可以避免这个问题。

 

如果大家有在存储过程中解决这个问题的办法,请不吝赐教。

备注:本文说的是MS SQL Server2000 的数据库,而非使用SQL 2005的新特性分页。

posted on 2007-03-09 18:16 玉开 阅读(4242) 评论(66)  编辑 收藏 所属分类: 数据库

FeedBack:
#1楼  2007-03-09 18:39 jyk [未注册用户]
只能说找到了一个不好的方法。

在存储过程里面“组串”本来就没有什么优势可言的。存在注入也是很正常的。

http://blog.csdn.net/jyk/archive/2007/03/01/1518354.aspx

这是我的分页控件的思路,里面有几个分页的算法。
  回复  引用    
#2楼  2007-03-09 18:47 jyk [未注册用户]
我看了您的《三层开发中容易犯的错误》。

有几个地方您是否注意到了。

1、层与层之间的衔接,您注意到了吗?是否会有过渡的部分而无法准确的被划分到哪一层。

2、.aspx是UI层,这个没有什么争议,那么.aspx.cs文件呢?也是UI层吗?

3、业务逻辑的本质是什么?我觉得本质就是SQL语句,写在程序里也好,写在存储过程里也好,这个并不是重点。重点是如何体现业务逻辑。业务层到底放什么?能起到什么作用。


以上是瞎说的,说错了不要生气。


  回复  引用    
#3楼  2007-03-09 18:48 生米煮成稀饭      
注意:很显然我们使用SqlParameter传递参数已经将单引号替换成了双引号了,不是双引号,是两个单引号,通过存储过程传参数,不会有这个问题。
  回复  引用  查看    
#4楼  2007-03-09 19:00 jyk [未注册用户]
您有没有试过替换成 四个“'” 就是 ''''



  回复  引用    
#5楼 [楼主] 2007-03-09 19:05 玉开      
@生米煮成稀饭
谢谢更正,那个是笔误,不过你的说法不正确,你可以做个试验

  回复  引用  查看    
#6楼 [楼主] 2007-03-09 19:05 玉开      
@jyk
替换成四个也会截断,虽然不能注入了,但是也不能正常执行了
  回复  引用  查看    
#7楼 [楼主] 2007-03-09 19:10 玉开      
@生米煮成稀饭
因为是在存储过程中拼串,所以即使替换了也是不正确的。
  回复  引用  查看    
#8楼  2007-03-09 19:24 生米煮成稀饭      
怎么会不正确呢?肯定是不会报错的
  回复  引用  查看    
#9楼 [楼主] 2007-03-09 19:24 玉开      
@生米煮成稀饭
你测试过吗?

  回复  引用  查看    
#10楼  2007-03-09 19:30 生米煮成稀饭      
我们可以假定用户输入的模糊用户名是: Jim’s dog

我们用SqlParameter传递参数给分页存储过程@strWhere 的值是:’UserName LIKE ‘’%Jim’’ dog%’’’

这个是怎么来的?你这个@strWhere是在哪里拼凑出这个结果的?程序里面?还是sql里面?
  回复  引用  查看    
#11楼  2007-03-09 19:31 生米煮成稀饭      
如果是在程序里面组合成整个’UserName LIKE ‘’%Jim’’ dog%’’’ 的话,你肯定是要进行字符串过滤的,如果只是把Jim’s dog 作为参数传进存储过程就不会出现你的问题了,我没有看你这个分页过程,但是,可以肯定的是,写的恰当的话,肯定不会出现你说的情况,因为我们一直都有在用分页存储过程。
  回复  引用  查看    
#12楼  2007-03-09 19:36 生米煮成稀饭      
还有,说一句,刚看了下这个存储过程,top来top去的效率基本上是接近最差了!
  回复  引用  查看    
#13楼  2007-03-09 19:49 YaziMyWife      
代码没有缩进 看起来好不爽啊!!
  回复  引用  查看    
#14楼 [楼主] 2007-03-09 19:51 玉开      
@生米煮成稀饭
是在程序里面拼得然后传给存储过程。
  回复  引用  查看    
#15楼 [楼主] 2007-03-09 19:55 玉开      
@YaziMyWife
其实那个存储过程就是常用的用top的分页存储过程
  回复  引用  查看    
#16楼 [楼主] 2007-03-09 20:00 玉开      
@生米煮成稀饭
你可不可以把你经常用的存储过程贴出来看看
  回复  引用  查看    
#17楼  2007-03-09 20:11 yzx110 [未注册用户]
我一直没相信这样的存储过程能够避免SQL注入

因为拼SQL字符串,天知道组合SQL字符串的各个是什么内容。

因为你拼得SQL字符串并不是待参数的执行方式,那么理论上就是你传入什么东西那么拼接之后就是什么东西,既然是这样,那么怎样就确定不能SQL注入。

除非你在应用把引号等敏感字符过滤掉,但是这跟存储过程能避免SQL注入有什么关系呢?
  回复  引用    
#18楼 [楼主] 2007-03-09 20:13 玉开      
@yzx110
谢谢,知音出现了,这确实是一种很大的安全漏洞
  回复  引用  查看    
#19楼  2007-03-09 20:23 冲啊!为了钱~      
学习下,大家加油吧<br>

  回复  引用  查看    
#20楼  2007-03-09 20:57 Jeffrey Zhao      
“存储过程能够避免Sql注入”这个说法本来就是错误的!
出现Sql Injection的问题在于拼接字符串而不是有没有用存储过程。
在存储过程里拼接字符串也会造成Sql Injection,直接在代码写带参数的Sql语句然后设置参数也不会有Sql Injection。
// latency sql injection不在目前的讨论范围中
  回复  引用  查看    
#21楼  2007-03-09 21:17 电子网 [未注册用户]
我看了您的《三层开发中容易犯的错误》。

有几个地方您是否注意到了。

1、层与层之间的衔接,您注意到了吗?是否会有过渡的部分而无法准确的被划分到哪一层。

2、.aspx是UI层,这个没有什么争议,那么.aspx.cs文件呢?也是UI层吗?

3、业务逻辑的本质是什么?我觉得本质就是SQL语句,写在程序里也好,写在存储过程里也好,这个并不是重点。重点是如何体现业务逻辑。业务层到底放什么?能起到什么作用。


以上是瞎说的,说错了不要生气。

  回复  引用    
这么厉害




ET电子技术网
http://www.et-dz.com
  回复