动态SQL的SQL端白名单有问题吗?

问题描述 投票:0回答:1

我有一个应用程序,希望从数据库中生成历史图表。这些图表可以是存储在我们表中的许多不同参数,并带有关联的日期时间。

存储过程将包含以下内容:

CREATE PROCEDURE [dbo].[getLog]
    -- Add the parameters for the stored procedure here

    @getIdEntity INT = 0 ,
    @columnName VARCHAR(100),
    @startDate DATETIME2,
    @endDate DATETIME2

AS
    SELECT logs.[DateTime], 
        logs.@column1 as Property
        from dbo.LogTable logs
    WHERE logs.[IdEntity] = @IdEntity AND logs.[DateTime] >= @startDate
    AND logs.[DateTime] <= @endDate 
    AND logs.column1 IS NOT NULL;'

这不起作用,无法将列作为参数插入。

答案当然是动态SQL,这显然会导致SQL注入问题。

该过程将变为:

ALTER PROCEDURE [dbo].[getLog]
    -- Add the parameters for the stored procedure here

    @getIdEntity INT = 0 ,
    @columnName VARCHAR(100),
    @startDate DATETIME2,
    @endDate DATETIME2

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    -- Insert statements for procedure here



    DECLARE 
    @dynamicSql NVARCHAR(500),
    @timespan INT

    SET @dynamicSql = '
        SELECT [DateTime],  
        [' +@columnName+'] as Property from dbo.EntityTransactionLogEntry etl 
        WHERE etl.[IdEntity] = '+ CAST(@getIdEntity AS VARCHAR(10))
        + ' AND etl.[DateTime] >= '''+ (CONVERT (VARCHAR(50),@startDate,121)) +''''
        + ' AND etl.[DateTime] <= '''+ (CONVERT (VARCHAR(50),@endDate,121)) +''''
        + ' AND etl.[' +@columnName+'] IS NOT NULL;
    EXEC (@dynamicSql)'

显然仍然容易受到SQL注入的攻击。

只是添加:

IF NOT EXISTS (SELECT * FROM 
            INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_NAME = 'EntityTransactionLogEntry'
            AND COLUMN_NAME = @columnName)
BEGIN
    PRINT  'Bad Input'
    RETURN
END

((我还限制了可查询的最大时间跨度,但我对此并不担心)在动态SQL部分足以保护它免受注入之前?它旨在失败,因为提供了无效的列名。

如果是,那么大概只创建一个我同意查询的列名的视图就可以限制可以使用的列?

我特别担心注射,但是我认为我很安全,只能从我们的API中获得。

c# sql sql-server sql-injection
1个回答
0
投票

欢迎翻转

您可以做一些类似的事情

parameters..
.. paramterx varchar(100) = null,
paramtery varchar(100) = null

select *
from entitytransactionlog
where
  logs.[IdEntity] = @IdEntity AND logs.[DateTime] >= @startDate
  AND logs.[DateTime] <= @endDate 
  and (columnvalue = parameterx or parameterx is null)
  and (columnvalue2 = parametery or parametery is null)

so sp的调用方式

exec sp parameterx = 'value'

如果没有定义参数中的值,则括号中的验证“ OR”将让每个值


0
投票

是否仅在动态SQL部分之前添加[在INFORMATION_SCHEMA中的检查?”足以保护其免受注入?

根据定义,不。仍在发生SQL注入。

从技术上讲,您要问的是从恶意 SQL注入是否安全。

您检查INFORMATION_SCHEMA是一种合理的保护。这是whitelisting的一种形式,这是我们必须用于无法由查询参数替代的事物的技术。

如果EntityTransactionLogEntry中有一列的名称可能会“破坏”定界标识符语法,那么您会遇到麻烦,但是我认为您可以控制自己表中的列名,并且您不会那。

您应将自己的INFORMATION_SCHEMA查询限制为自己的TABLE_SCHEMA。当前正在编写查询时,如果I_S中分类为any的表具有该列名,就可以满足要求。

此外,我不确定为什么您在IdEntity和DateTime的术语中不使用查询参数,其中值can被查询参数代替。您应该这样做。

© www.soinside.com 2019 - 2024. All rights reserved.