使用SQL Server中存储过程中的变量为参数赋值

时间:2018-02-21 09:57:18

标签: sql sql-server

我有一个带有一个参数@Name的简单存储过程,我想用另一个变量替换它。

我实际上在寻找SQL注入字符,如果名称包含--,那么它应该用空格替换它。下面显示的存储过程,它正在执行而没有错误,但是没有替换字符串,例如,让我们说用户搜索其中包含SQL注入语句的EXEC John'''select * FROM TEST2 --

CREATE PROCEDURE GetStudentDetails
    @Name nvarchar(300)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT @Name = REPLACE(@Name ,'--','');
    SET @Name = REPLACE(@Name ,'--','');

    SELECT * 
    FROM TABLENAME 
    WHERE Name LIKE N'%'+ @Name +'%'
END

更新了存储过程:

CREATE PROCEDURE GetStudentDetails
    @Name nvarchar(300)
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @SafeSearchItem   nvarchar(30);

    SELECT  @SafeSearchItem = REPLACE(@Name ,N'--',N'')
    SET  @SafeSearchItem = REPLACE(@Name ,N'--',N'')

    SELECT * 
    FROM TABLENAME 
    WHERE Name LIKE N'%'+ @SafeSearchItem +'%'
END

EXEC

EXEC John'''select * FROM TEST2 --

在第二个存储过程中,我总是能够注入SQL - 不确定它是我的系统吗?

1 个答案:

答案 0 :(得分:1)

目前我们无法回答这个问题,因为我们还没有提供适用于我们所提供信息的问题。在我们的SP中没有注射风险,因此,没有回答如何避免它。

无论如何,相反,我要做的是首先展示为什么SP不受注射然后改变它所以它会被修改,以及有限的"修复&#34 ;在其中很容易避免。

首先,让我们从一个简单的表格和数据开始(我强烈建议在Sandbox环境中运行以下任何脚本!):

USE Sandbox;
GO

CREATE TABLE InjectionReady (ID int IDENTITY(1,1), SomeText varchar(500));

INSERT INTO InjectionReady
VALUES ('Here is some text'),
       ('Life is like a box a chocolates'),
       ('Milk Chocolate is my favourite'),
       ('Cheese is dairy product'),
       ('Chocolate is a dairy product'),
       ('Cows say "moo"!'),
       ('English Cat says "Meow"'),
       ('Japanese Cat says "Nyaa"');
GO

好的,现在让我们创建你的SP(为我们的对象修改)。然后做一些测试:

CREATE PROCEDURE NonInjectionSearch @Wildcard nvarchar(100) AS


    SELECT @Wildcard = REPLACE(@Wildcard ,N'--',N'');
    SET @Wildcard = REPLACE(@Wildcard ,N'--',N'');

    SELECT *
    FROM InjectionReady
    WHERE SomeText LIKE N'%'+ @Wildcard +N'%';

GO
EXEC NonInjectionSearch 'Chocolate';
EXEC NonInjectionSearch '''; DROP TABLE InjectionReady;--';
EXEC NonInjectionSearch '''; DROP TABLE InjectionReady; SELECT ''';

没有注射。大!好的,现在对于可以遭受注射的SP:

CREATE PROCEDURE InjectionSearch @Wildcard nvarchar(100) AS


    SELECT @Wildcard = REPLACE(@Wildcard ,N'--',N'');
    SET @Wildcard = REPLACE(@Wildcard ,N'--',N'');

    DECLARE @SQL nvarchar(MAX);
    SET @SQL = N'
    SELECT *
    FROM InjectionReady
    WHERE SomeText LIKE N''%'+ @Wildcard + N'%'';'; --Yes, intentional non parametrisation
    PRINT @SQL;
    EXEC (@SQL);

GO
EXEC InjectionSearch 'Chocolate';
GO
EXEC InjectionSearch '''; CREATE TABLE Injection1(ID int);--'; --This'll fail
GO
EXEC InjectionSearch '''; CREATE TABLE Injection2(ID int); SELECT '''; --Oh! This worked!

GO

那么,你怎么能避免这种情况呢?好吧,参数化你的动态SQL:

CREATE PROCEDURE ParamSearch @Wildcard nvarchar(100) AS

    DECLARE @SQL nvarchar(MAX);
    SET @SQL = N'
    SELECT *
    FROM InjectionReady
    WHERE SomeText LIKE N''%'' + @pWildCard +''%'';'; --Yes, intentional non parametrisation
    PRINT @SQL;
    EXEC sp_executesql @SQL, N'@pWildcard nvarchar(500)', @pWildCard = @Wildcard;
GO

EXEC ParamSearch 'Chocolate';
GO
EXEC ParamSearch '''; CREATE TABLE Injection1(ID int);--'; --Won't inject
GO
EXEC ParamSearch '''; CREATE TABLE Injection2(ID int); SELECT '''; --Oh! this didn't inject either

动态对象为此带来了另一个层次,但是,如果需要,我只会覆盖它;就像它一样(就像我在开始时说的那样),我们所拥有的场景可能会出现问题。

清理:

DROP TABLE Injection2;
DROP PROC ParamSearch;
DROP PROC InjectionSearch;
DROP PROC NonInjectionSearch;
DROP TABLE InjectionReady;