(二)SQL 注入
SQL注入就不用介绍了,网上很多。下面介绍一下防止SQL注入的方法。
使用quotename 函数和 sp_executesql
参考如下表结构:这是一个文档表里面有一些简单的字段信息
CREATE TABLE [dbo].[DocumentInfo](
[ID] [int] IDENTITY(1,1) primary key NOT NULL,--主键
[Name] [varchar](100) NOT NULL,--文档名字
[FunctionID] [int] NOT NULL,--功能ID外键
[TypeInfo] [nvarchar](2000) NULL—描述信息
)
我们可能会按,主键ID,文档的名字,功能id, 描述信息进行查询 ,这个一看就是拼接sql语句,如果不用上面的方法很可能造成sql注入
例如你写的存储过程可能如下:
CREATE proc [dbo].[Doc_search]
(
@ID int,
@name varchar(10),
@FID int,
@Info nvarchar(20)
)
as
begin
declare @sql varchar(300)
set @sql='select * from [DocumentInfo] where 1=1'
if @ID<>-1
set @sql=@sql+' and ID='+CAST(@ID as varchar)
if @name<>''
set @sql=@sql+' and name='''+CAST(@name as varchar) +''''
if @FID<>-1
set @sql=@sql+' and [FunctionID]='+CAST(@FID as varchar)
if @Info <>''
set @sql=@sql+ ' and [TypeInfo] like ''%'+CAST(@Info as varchar)+'%'''
print @sql
end
exec(@sql)
虽然你用了带参数的存储过程 ,但本质上还是拼接字符串,没有有效的防治sql注入。现在分别用quotename()函数和sp_executesql。Quotename()函数不知道用的请自行查找,sp_executesql的用法见上一篇动态sql
Quotename改进如下:
alter proc [dbo].[Doc_search]
(
@ID int,
@name varchar(10),
@FID int,
@Info nvarchar(20)
)
as
begin
declare @sql varchar(300)
set @sql='select * from [DocumentInfo] where 1=1'
if @ID<>-1
set @sql=@sql+' and ID='+CAST(@ID as varchar)
if @name<>''
set @sql=@sql+' and name='+QUOTENAME(@name,'''')
if @FID<>-1
set @sql=@sql+' and [FunctionID]='+CAST(@FID as varchar)
if @Info <>''
set @Info='%'+@Info+'%';
set @sql=@sql+ ' and [TypeInfo] like '+QUOTENAME(@Info,'''')
print @sql
end
exec(@sql)
但这种方法碰到字段是Int类型的就会失效
所以推荐使用sp_executesql 改进存储过程如下:
alter proc [dbo].[Doc_search]
(
@ID int,
@name varchar(10),
@FID int,
@Info nvarchar(20)
)
as
begin
declare @sql nvarchar(300)
set @sql=N'select * from [DocumentInfo] where 1=1'
if @ID<>-1
set @sql=@sql+' and ID=@ID'
if @name<>''
set @sql=@sql+' and name=@name'
if @FID<>-1
set @sql=@sql+' and [FunctionID]=@FID'
if @Info <>''
set @Info='%'+@Info+'%';
set @sql=@sql+ ' and [TypeInfo] like @Info'
print @sql
end
exec sp_executesql @sql ,N'@ID as int,@name as varchar(10),@FID as int,@Info as nvarchar(20)',@ID,@Name ,@FID,@Info
这样参数化才是真的参数化 注意like的用法。用’’Sql注入第一种 然后再注入第三种会发现得不到你想要的结果。sp_executesql 还是非常有用的 下一篇介绍 用sp_executesql 怎样实现比较通用的分页存储过程
作 者:
出 处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面 明显位置给出原文连接,否则保留追究法律责任的权利。