2014-11-30 3 views
2

Я использую SQL Server 2012, и я пишу хранимую процедуру.SQL Server Хранимая процедура и SQL-инъекция

Я хочу знать, есть ли какая-либо возможность SQL-инъекции в моей хранимой процедуре?

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL 
    DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
    @productname AS NVARCHAR(40) 
    , @supplierid AS INT 
    , @categoryid AS INT 
    , @unitprice AS MONEY = 0 
    , @discontinued AS BIT = 0 
AS 
BEGIN 
    INSERT Production.Products (productname, supplierid, categoryid, unitprice, discontinued) 
    VALUES (@productname, @supplierid, @categoryid, @unitprice, @discontinued); 

    RETURN; 
END; 
GO 

Или

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL 
    DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
    @productname AS NVARCHAR(40) 
    , @supplierid AS INT 
    , @categoryid AS INT 
    , @unitprice AS MONEY = 0 
    , @discontinued AS BIT = 0 
AS 
BEGIN 
    Declare @Command NVArchar(Max) = 'INSERT Production.Products (productname, supplierid, categoryid, unitprice, discontinued) 
    VALUES (''' + @productname + ''',' + @supplierid + ',' + @categoryid + ',' + @unitprice + ',' + @discontinued + ');' 
    Execute(@Command); 
    RETURN; 
END; 
GO 

Или

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL 
    DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
    @productname AS NVARCHAR(40) 
    , @supplierid AS INT 
    , @categoryid AS INT 
    , @unitprice AS MONEY = 0 
    , @discontinued AS BIT = 0 
AS 
BEGIN 
    Declare @Command NVArchar(Max) = ' 
    INSERT Production.Products (productname, supplierid, categoryid, 
    unitprice, discontinued) 
    VALUES (@productname , @supplierid,@categoryid,@unitprice,@discontinued);' 

Execute SP_ExecuteSql @Command, 
    ' @productname NVARCHAR(40) , @supplierid INT , @categoryid INT 
     , @unitprice MONEY , @discontinued BIT ' , 
     @productname= @productname,@[email protected], 
     @[email protected],@[email protected],@[email protected] 
    RETURN; 
END; 
GO 

Какой из этих запросов лучше всего?

+0

Почему вы используете RETURN ;? – HaveNoDisplayName

+0

Возврат не имеет значения, когда он использовался в последней строке SP. –

+0

вот мой вопрос, тогда почему вы его используете, удалите это. – HaveNoDisplayName

ответ

4

Что касается самих хранимых процедур.

Первый не имеет возможности для SQL-инъекции, потому что нет динамического SQL.

Третий не имеет возможности для SQL-инъекции, поскольку использование sp_executesql компилирует запрос с параметрами, а затем вставляет значения параметров. В компиляции логически происходит до подстановка параметров, поэтому фанковые строки в параметрах не могут изменить тот факт, что будет работать только один insert.

Второй уязвим, из-за @productname. Другими параметрами являются числа, и я не думаю, что включение чисел в строку может вызвать уязвимость. (Если я ошибаюсь, я уверен, что кто-то укажет ссылку на то, как это будет работать.) Существует риск с такими параметрами, потому что кто-то может изменить их на символьные строки в будущем.

С точки зрения безопасности и лучших практик, первая версия является самой безопасной. Вам даже не нужно думать о том, есть ли уязвимость. Третий безопасен, но может не выглядеть безопасным. Во-вторых, следует избегать, если вас вообще беспокоит SQL-инъекция.

Что касается использования return, у меня нет проблем с ним. Это четкое изложение намерения программиста прекратить выполнение хранимой процедуры в этой точке. И на самом деле SQL Server documentation имеет избыточный пример. Хранимые процедуры do Возвращаемые значения, всегда целочисленный код состояния, и я обычно использую их.

Смежные вопросы