Как защитить динамическую хранимую процедуру SQL?

У меня есть хранимая процедура, которая принимает имя таблицы в качестве параметра и использует динамический sql для выполнения выбора. Я попытался передать @TableName в качестве параметра и использовать sp_executesql, но это вызвало ошибку. Я решил использовать прямой динамический sql без использования sp_executesql.

Есть ли что-нибудь еще, что мне нужно сделать, чтобы защитить параметр @TableName, чтобы избежать атак с использованием sql-инъекций?

Сохраненная процедура ниже:

CREATE PROCEDURE dbo.SP_GetRecords  
    (   
    @TableName VARCHAR(128) = NULL
    )   
AS
BEGIN   

    /* Secure the @TableName Parameter */          
    SET @TableName = REPLACE(@TableName, ' ','')    
    SET @TableName = REPLACE(@TableName, ';','')    
    SET @TableName = REPLACE(@TableName, '''','')

    DECLARE @query NVARCHAR(MAX)    

    /* Validation */    
    IF @TableName IS NULL
    BEGIN       
        RETURN -1
    END 

    SET @query = 'SELECT * FROM ' + @TableName
    EXEC(@query)        
END

Это не удалось при использовании вместо этого sp_executesql:

SET @query = 'SELECT * FROM @TableName' 
EXEC sp_executesql @query, N'@TableName VARCHAR(128)', @TableName

ОШИБКА: необходимо объявить табличную переменную «@TableName».


person Crackerjack    schedule 12.01.2011    source источник
comment
Какое бы решение вы ни выбрали, имейте в виду, что когда вы выполняете динамический SQL в хранимой процедуре, этот SQL запускается по умолчанию с разрешениями хранимой процедуры вызывающей стороны. В то время как обычный SQL в хранимой процедуре запускается по умолчанию с разрешениями владельца хранимой процедуры.   -  person HTTP 410    schedule 12.01.2011


Ответы (2)


Посмотреть здесь:

Как передать таблицу имя в сохраненную процедуру?

person RBarryYoung    schedule 12.01.2011
comment
Отлично, это именно то, что я искал - person Crackerjack; 12.01.2011

вы, конечно, можете посмотреть таблицу sysobjects и убедиться, что она существует

Select id from sysobjects where xType = 'U' and [name] = @TableName

Далее (более полный пример):

DECLARE @TableName nVarChar(255)
DECLARE @Query nVarChar(512)

SET @TableName = 'YourTable'
SET @Query = 'Select * from ' + @TableName

-- Check if @TableName is valid
IF NOT (Select id from sysobjects where xType = 'U' and [name] = @TableName) IS NULL
     exec(@Query)
person Jason Benson    schedule 12.01.2011
comment
Не будет ли небезопасная строка по-прежнему включена в запрос для проверки существования таблиц? - person jason saldo; 12.01.2011
comment
@jms, но здесь вы можете использовать параметры привязки - person Markus Winand; 12.01.2011