如此高效通用的分页存储过程是带有sql注入漏洞的

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

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

 

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

 

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

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 通用分页存储过程
img_a6339ee3e57d1d52bc7d02b338e15a60.gifCREATE PROCEDURE pagination
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@tblName varchar(255), -- 表名 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@strGetFields varchar(1000= '*'-- 需要返回的列 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@fldName varchar(255)=''-- 排序的字段名 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@PageSize int = 10-- 页尺寸 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@PageIndex int = 1-- 页码 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@doCount bit = 0-- 返回记录总数, 非 0 值则返回 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@OrderType bit = 0-- 设置排序类型, 非 0 值则降序 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
@strWhere varchar(1500= '' -- 查询条件 (注意: 不要加 where) 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
AS 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
declare @strSQL varchar(5000-- 主语句 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
declare @strTmp varchar(110-- 临时变量 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
declare @strOrder varchar(400-- 排序类型 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @doCount != 0 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @strWhere !='' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where '+@strWhere 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
else 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select count(*) as Total from [' + @tblName + ']' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif

img_a6339ee3e57d1d52bc7d02b338e15a60.gif
else 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @OrderType != 0 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strTmp = '<(select min' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strOrder = ' order by [' + @fldName +'] desc' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
--如果@OrderType不是0,就执行降序,这句很重要! 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
else 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strTmp = '>(select max' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strOrder = ' order by [' + @fldName +'] asc' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @PageIndex = 1 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @strWhere != '' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select top ' + str(@PageSize+' '+@strGetFields+ ' from [' + @tblName + '] where ' + @strWhere + ' ' + @strOrder 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
else 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select top ' + str(@PageSize+' '+@strGetFields+ ' from ['+ @tblName + ''+ @strOrder 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
--如果是第一页就执行以上代码,这样会加快执行速度 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
else 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
begin 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
--以下代码赋予了@strSQL以真正执行的SQL代码 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select top ' + str(@PageSize+' '+@strGetFields+ ' from [' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize+ ' ['+ @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'+ @strOrder 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
if @strWhere != '' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
set @strSQL = 'select top ' + str(@PageSize+' '+@strGetFields+ ' from [' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '([' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
+ @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize+ ' [' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' ' 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
end 
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
exec (@strSQL)
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
GO
img_a6339ee3e57d1d52bc7d02b338e15a60.gif
img_a6339ee3e57d1d52bc7d02b338e15a60.gif

 

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

 

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

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

 

为了便于说明问题,我们可以假定

@pageSize 20 @strGetFields ‘*’ @tblName UserAccount,@strOrder ’ ORDER  BY  ID DESC’ 那么上面一行可以写成如下形式:

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

 

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

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

 

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

 

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

 

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


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

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

 

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

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

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

 

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

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

目录
相关文章
|
2天前
|
SQL 运维 安全
WAF如何防御SQL注入?
【7月更文挑战第25天】WAF如何防御SQL注入?
21 9
|
2天前
|
SQL 安全 数据库
从入门到精通:Python Web安全守护指南,SQL注入、XSS、CSRF全防御!
【7月更文挑战第25天】在Python Web开发中确保应用安全至关重要。以下是针对SQL注入、XSS与CSRF攻击的防护策略及示例代码
19 6
|
2天前
|
SQL 安全 数据库
|
2天前
|
SQL 存储 安全
Python Web安全大挑战:面对SQL注入、XSS、CSRF,你准备好了吗?
【7月更文挑战第25天】在Python Web应用开发中,安全至关重要,需防范如SQL注入、XSS与CSRF等攻击。**SQL注入**风险可通过避免直接拼接用户输入至SQL语句,改用参数化查询来缓解。**XSS**则需对用户输入的内容进行HTML转义处理,防止恶意脚本执行。对于**CSRF**,实现包括生成并验证CSRF令牌在内的防护机制是关键。综合运用这些防御策略能显著增强应用的安全性,但需持续学习以对抗不断变化的威胁。
16 5
|
1天前
|
SQL 安全 Go
SQL注入不可怕,XSS也不难防!Python Web安全进阶教程,让你安心做开发!
【7月更文挑战第26天】在 Web 开发中, SQL 注入与 XSS 攻击常令人担忧, 但掌握正确防御策略可化解风险. 对抗 SQL 注入的核心是避免直接拼接用户输入至 SQL 语句. 使用 Python 的参数化查询 (如 sqlite3 库) 和 ORM 框架 (如 Django, SQLAlchemy) 可有效防范. 防范 XSS 攻击需严格过滤及转义用户输入. 利用 Django 模板引擎自动转义功能, 或手动转义及设置内容安全策略 (CSP) 来增强防护. 掌握这些技巧, 让你在 Python Web 开发中更加安心. 安全是个持续学习的过程, 不断提升才能有效保护应用.
7 1
|
1天前
|
SQL 安全 前端开发
Web安全新纪元:Python如何筑起SQL注入、XSS、CSRF的铜墙铁壁?
【7月更文挑战第26天】在Web开发中,安全性至关重要。Python提供强大工具来抵御SQL注入、XSS和CSRF等威胁。使用ORM如Django和SQLAlchemy可防SQL注入; Django等框架自动转义输出防XSS; CSRF通过自动及手动验证令牌来阻止。开发者须持续学习最新安全实践以保护用户数据。迈向Web安全新纪元,Python助你一臂之力。
7 1
|
15天前
|
SQL 安全 网络安全
Victor CMS v1.0 SQL 注入(CVE-2022-26201)
Victor CMS v1.0 SQL 注入(CVE-2022-26201)
|
14天前
|
SQL API Python
`bandit`是一个Python静态代码分析工具,专注于查找常见的安全漏洞,如SQL注入、跨站脚本(XSS)等。
`bandit`是一个Python静态代码分析工具,专注于查找常见的安全漏洞,如SQL注入、跨站脚本(XSS)等。