尝试使用通用SP作为SELECT的模板(用于反注入目的)

时间:2013-07-07 00:00:32

标签: sql sql-server stored-procedures sql-injection

计划使用:

例如:

tableName = TableCustomers 
column1 = UserName
column2 = UserMail
-- SP name ......and as zero will select all *, 'firstColName'....
SelectFromGivenTableWithOptionalGivenColumn, 0, 'UserName', '', 'AnyUserName', ''

或更好地从SSMS生成的执行脚本

复制
USE [KwPos]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[SelectFromGivenTableWithOptionalGivenColumns]
    @tableName = 'TableCustomers',
    @zeroForAllTable = 0,
    @Column = 'UserName',
    @Column2 = '',
    @ColVal = 'AnyUserName',
    @ColVal2 = ''

错误

Invalid column name 'AnyUserName'.

这是SP的SQL(尝试使用SysName& nvarchar的两个列名称导致相同的错误)

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SelectFromGivenTableWithOptionalGivenColumns] 
    @tableName sysname ='', 
    @zeroForAllTable bit = 0,
    @Column sysname = '',
    @Column2 sysname = '',  
    @ColVal varchar(111) = '',
    @ColVal2 varchar(111) = ''
AS
BEGIN
    SET NOCOUNT ON;

    declare @q varchar(1000)
    if(@zeroForAllTable !=0)
        begin
            if(@Column !='' AND @Column2 !='')
                begin
                    if(@Column != '' AND @ColVal !='' AND @Column2 != '' AND @ColVal2 !='')
                        begin   
                            set @q= 'SELECT ' + @Column + ' FROM ' + @tableName + ' where ' + @Column + ' = ' + @ColVal + ' AND ' + @Column2 + ' = ' + @ColVal2;
                        end
                    else if(@Column !='' AND @ColVal ='')
                        begin
                            set @q = 'SELECT '+ @Column +' FROM ' + @tableName;
                        end
                end
            else
            if(@Column !='' AND @Column = '')
                begin
                    if(@Column != '' AND @ColVal !='')
                        begin   
                            set @q= 'SELECT ' + @Column + ' FROM ' + @tableName + ' where ' + @Column + ' = ' + @ColVal;
                        end
                    else if(@Column !='' AND @ColVal ='')
                        begin
                            set @q = 'SELECT '+ @Column + ' FROM ' + @tableName;
                        end
                end
        end
    else
        begin
            if(@Column !='' AND @Column2 !='')
                begin
                    if(@Column != '' AND @ColVal !='')
                        begin   
                            set @q= 'SELECT * FROM ' + @tableName + ' where ' + @Column+ ' = ' + @ColVal + ' AND ' + @Column2 + ' = ' + @ColVal2;
                        end
                    else if(@Column !='' AND @ColVal ='')
                        begin
                            set @q = 'SELECT * FROM ' + @tableName;
                        end
                end
            else
            if(@Column !='' AND @Column2 = '')
                begin
                    if(@Column != '' AND @ColVal !='')
                        begin   
                            set @q= 'SELECT * FROM ' + @tableName + ' where ' + @Column + ' = ' + @ColVal;
                        end
                    else if(@Column !='' AND @ColVal ='')
                        begin
                            set @q = 'SELECT * FROM ' + @tableName;
                        end
                    else 
                        begin
                            set @q = 'SELECT * FROM ' + @tableName;
                        end
                end
        end

    exec (@q)

END
GO

2 个答案:

答案 0 :(得分:1)

好吧,你刚刚停止了SQL注入。通过动态创建查询而无需正确编码值,您可能会为SQL注入打开一个巨大的漏洞。

您尝试创建的查询是:

SELECT * FROM TableCustomers where UserName = 'AnyUserName'

但你创建了:

SELECT * FROM TableCustomers where UserName = AnyUserName

您可以添加缺失的撇号,但注射孔仍然打开。想象一下,用户名是从用户输入的,而不是输入AnyUserName他输入的';drop table TableCustomers;--,然后查询将是:

SELECT * FROM TableCustomers where UserName = '';drop table TableCustomers;--'
哎呀,你的桌子不见了。

(必修XKCD参考:http://xkcd.com/327/

答案 1 :(得分:0)

取自Link (第3个例子)

这段代码足够安全吗?

DECLARE @sqlCommand nvarchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

我的意思是......你很容易还有可能在这里杀死一些数据吗?