存储过程SQL注入检查
Stored procedure SQL Injection check
我写了下面的查询数据库的存储过程。谁能告诉我这个动态查询存储过程是否容易受到 SQL 注入攻击?
如果是,如何修改下面的代码来防止SQL注入攻击?
第二个问题是OPTION (RECOMPILE)
在WHERE
原因的最后,是否每次执行都需要?
CREATE PROCEDURE DataMapMainQuery
(@DataMapID VARCHAR(MAX),
@DataMapIDName VARCHAR(MAX),
@StartIndex INT,
@MaximumRows INT,
@sortExpression VARCHAR(MAX))
AS
BEGIN
DECLARE @FilteredTotalRows AS INT
DECLARE @SqlString NVARCHAR(MAX)
DECLARE @WhereString1 NVARCHAR(MAX)
DECLARE @WhereString2 NVARCHAR(MAX)
IF (@DataMapID IS NULL)
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%' + @DataMapID + '%''' + ' OR ''' + @DataMapID + ''' IS NULL)'
IF (@DataMapIDName IS NULL)
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%' + @DataMapIDName + '%''' + ' OR ''' + @DataMapIDName + ''' IS NULL)'
IF (@sortExpression IS NULL)
SET @sortExpression = 'DataMapID'
SELECT
@FilteredTotalRows = COUNT(*)
FROM
DataMapMain
WHERE
1 = 1
AND (DataMapID LIKE '%' + @DataMapID + '%' OR @DataMapID IS NULL)
AND (DataMapIDName LIKE '%' + @DataMapIDName + '%' OR @DataMapIDName IS NULL)
IF (@FilteredTotalRows < @StartIndex + 1)
BEGIN
SET @SqlString = '
SELECT
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
CONVERT(BIGINT, TimeStamp) AS TimeStamp
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowNumber,
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
TimeStamp
FROM
DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= 1
AND RowNumber < (1 + ' + CONVERT(NVARCHAR(10), @MaximumRows) + ')
OPTION (RECOMPILE)'
END
ELSE
BEGIN
SET @SqlString = '
SELECT
DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,CONVERT(bigint, TimeStamp) as TimeStamp
FROM
(
Select ROW_NUMBER() over (order by ' + @sortExpression + ') as RowNumber
,DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,TimeStamp
From DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1) and RowNumber < (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1 + ' + CONVERT(nvarchar(10),@MaximumRows) + ' )
OPTION (RECOMPILE)'
END
PRINT @SqlString
PRINT @FilteredTotalRows
EXEC sp_executesql @SqlString
END
到目前为止,您的 @DataMapID
和 @DataMapName
是安全的,因为您在将其应用到主 sql 查询之前首先构建它。我建议添加这些行来检查 sort expression, maxrows and start index
的正确值
IF (@sortExpression NOT IN ('ASC', 'DESC'))
BEGIN
RAISERROR('invalid order expression', 16,1);
RETURN;
END;
IF (TRY_CAST(@StartIndex as int) = null or TRY_CAST(@MaximumRows as int) = null)
BEGIN
RAISERROR('invalid startindex or maximum rows', 16,1);
RETURN;
END;
只需使用带参数的sp_executesql
。构建您的动态 T-SQL 语句,而不是值添加 @parameter_name
。然后像这样调用例程:
EXEC sp_executesql @sql
,N'@parameter_name1 INT, @parameter_name2 VARCHAR(128), @parameter_name3 BIT'
,@parameter_name1, @parameter_name2, @parameter_name3;
添加OPTION(RECOMPILE) 提示为每次执行的查询执行重建一个新的执行计划。在某些情况下,它可以帮助提高性能。然而,重新编译操作使用内存和 CPU 资源来生成新的执行计划。因此,如果您不确定性能效果,请不要使用它
感谢大家的帮助,我重写了下面的代码。如果不行,请告诉我。谢谢大家!
CREATE PROCEDURE DataMapMainQuery
(@DataMapID VARCHAR(MAX),
@DataMapIDName VARCHAR(MAX),
@StartIndex INT,
@MaximumRows INT,
@sortExpression VARCHAR(MAX))
AS
BEGIN
DECLARE @FilteredTotalRows AS INT
DECLARE @SqlString NVARCHAR(MAX)
DECLARE @params NVARCHAR(MAX);
DECLARE @WhereString1 NVARCHAR(MAX)
DECLARE @WhereString2 NVARCHAR(MAX)
IF (@DataMapID IS NULL)
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%' + @DataMapID + '%''' + ' OR ''' + @DataMapID + ''' IS NULL)'
IF (@DataMapIDName IS NULL)
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%' + @DataMapIDName + '%''' + ' OR ''' + @DataMapIDName + ''' IS NULL)'
IF (@sortExpression IS NULL)
SET @sortExpression = 'DataMapID'
SELECT
@FilteredTotalRows = COUNT(*)
FROM
DataMapMain
WHERE
1 = 1
AND (DataMapID LIKE '%' + @DataMapID + '%' OR @DataMapID IS NULL)
AND (DataMapIDName LIKE '%' + @DataMapIDName + '%' OR @DataMapIDName IS NULL)
IF (@FilteredTotalRows < @StartIndex + 1)
BEGIN
SET @SqlString = '
SELECT
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
CONVERT(BIGINT, TimeStamp) AS TimeStamp
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowNumber,
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
TimeStamp
FROM
DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= 1
AND RowNumber < (1 + ' + CONVERT(NVARCHAR(10), @MaximumRows) + ')'
END
ELSE
BEGIN
SET @SqlString = '
SELECT
DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,CONVERT(bigint, TimeStamp) as TimeStamp
FROM
(
Select ROW_NUMBER() over (order by ' + @sortExpression + ') as RowNumber
,DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,TimeStamp
From DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1) and RowNumber < (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1 + ' + CONVERT(nvarchar(10),@MaximumRows) + ' )'
END
SET @params = '
@DataMapID VARCHAR(MAX)
,@DataMapIDName VARCHAR(MAX)
,@StartIndex INT
,@MaximumRows INT
,@sortExpression VARCHAR(MAX)';
EXEC sp_executesql
@SqlString
,@params
,@DataMapID
,@DataMapIDName
,@StartIndex
,@MaximumRows
,@sortExpression;
END
我写了下面的查询数据库的存储过程。谁能告诉我这个动态查询存储过程是否容易受到 SQL 注入攻击?
如果是,如何修改下面的代码来防止SQL注入攻击?
第二个问题是OPTION (RECOMPILE)
在WHERE
原因的最后,是否每次执行都需要?
CREATE PROCEDURE DataMapMainQuery
(@DataMapID VARCHAR(MAX),
@DataMapIDName VARCHAR(MAX),
@StartIndex INT,
@MaximumRows INT,
@sortExpression VARCHAR(MAX))
AS
BEGIN
DECLARE @FilteredTotalRows AS INT
DECLARE @SqlString NVARCHAR(MAX)
DECLARE @WhereString1 NVARCHAR(MAX)
DECLARE @WhereString2 NVARCHAR(MAX)
IF (@DataMapID IS NULL)
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%' + @DataMapID + '%''' + ' OR ''' + @DataMapID + ''' IS NULL)'
IF (@DataMapIDName IS NULL)
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%' + @DataMapIDName + '%''' + ' OR ''' + @DataMapIDName + ''' IS NULL)'
IF (@sortExpression IS NULL)
SET @sortExpression = 'DataMapID'
SELECT
@FilteredTotalRows = COUNT(*)
FROM
DataMapMain
WHERE
1 = 1
AND (DataMapID LIKE '%' + @DataMapID + '%' OR @DataMapID IS NULL)
AND (DataMapIDName LIKE '%' + @DataMapIDName + '%' OR @DataMapIDName IS NULL)
IF (@FilteredTotalRows < @StartIndex + 1)
BEGIN
SET @SqlString = '
SELECT
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
CONVERT(BIGINT, TimeStamp) AS TimeStamp
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowNumber,
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
TimeStamp
FROM
DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= 1
AND RowNumber < (1 + ' + CONVERT(NVARCHAR(10), @MaximumRows) + ')
OPTION (RECOMPILE)'
END
ELSE
BEGIN
SET @SqlString = '
SELECT
DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,CONVERT(bigint, TimeStamp) as TimeStamp
FROM
(
Select ROW_NUMBER() over (order by ' + @sortExpression + ') as RowNumber
,DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,TimeStamp
From DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1) and RowNumber < (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1 + ' + CONVERT(nvarchar(10),@MaximumRows) + ' )
OPTION (RECOMPILE)'
END
PRINT @SqlString
PRINT @FilteredTotalRows
EXEC sp_executesql @SqlString
END
到目前为止,您的 @DataMapID
和 @DataMapName
是安全的,因为您在将其应用到主 sql 查询之前首先构建它。我建议添加这些行来检查 sort expression, maxrows and start index
IF (@sortExpression NOT IN ('ASC', 'DESC'))
BEGIN
RAISERROR('invalid order expression', 16,1);
RETURN;
END;
IF (TRY_CAST(@StartIndex as int) = null or TRY_CAST(@MaximumRows as int) = null)
BEGIN
RAISERROR('invalid startindex or maximum rows', 16,1);
RETURN;
END;
只需使用带参数的sp_executesql
。构建您的动态 T-SQL 语句,而不是值添加 @parameter_name
。然后像这样调用例程:
EXEC sp_executesql @sql
,N'@parameter_name1 INT, @parameter_name2 VARCHAR(128), @parameter_name3 BIT'
,@parameter_name1, @parameter_name2, @parameter_name3;
添加OPTION(RECOMPILE) 提示为每次执行的查询执行重建一个新的执行计划。在某些情况下,它可以帮助提高性能。然而,重新编译操作使用内存和 CPU 资源来生成新的执行计划。因此,如果您不确定性能效果,请不要使用它
感谢大家的帮助,我重写了下面的代码。如果不行,请告诉我。谢谢大家!
CREATE PROCEDURE DataMapMainQuery
(@DataMapID VARCHAR(MAX),
@DataMapIDName VARCHAR(MAX),
@StartIndex INT,
@MaximumRows INT,
@sortExpression VARCHAR(MAX))
AS
BEGIN
DECLARE @FilteredTotalRows AS INT
DECLARE @SqlString NVARCHAR(MAX)
DECLARE @params NVARCHAR(MAX);
DECLARE @WhereString1 NVARCHAR(MAX)
DECLARE @WhereString2 NVARCHAR(MAX)
IF (@DataMapID IS NULL)
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString1 = ' AND (DataMapID LIKE ' + '''%' + @DataMapID + '%''' + ' OR ''' + @DataMapID + ''' IS NULL)'
IF (@DataMapIDName IS NULL)
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%%''' + ' OR NULL IS NULL)'
ELSE
SET @WhereString2 = ' AND (DataMapIDName LIKE ' + '''%' + @DataMapIDName + '%''' + ' OR ''' + @DataMapIDName + ''' IS NULL)'
IF (@sortExpression IS NULL)
SET @sortExpression = 'DataMapID'
SELECT
@FilteredTotalRows = COUNT(*)
FROM
DataMapMain
WHERE
1 = 1
AND (DataMapID LIKE '%' + @DataMapID + '%' OR @DataMapID IS NULL)
AND (DataMapIDName LIKE '%' + @DataMapIDName + '%' OR @DataMapIDName IS NULL)
IF (@FilteredTotalRows < @StartIndex + 1)
BEGIN
SET @SqlString = '
SELECT
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
CONVERT(BIGINT, TimeStamp) AS TimeStamp
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ' + @sortExpression + ') AS RowNumber,
DataMapID, DataMapIDName,
DataMapGroup, DataMapGroupRemark,
TimeStamp
FROM
DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= 1
AND RowNumber < (1 + ' + CONVERT(NVARCHAR(10), @MaximumRows) + ')'
END
ELSE
BEGIN
SET @SqlString = '
SELECT
DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,CONVERT(bigint, TimeStamp) as TimeStamp
FROM
(
Select ROW_NUMBER() over (order by ' + @sortExpression + ') as RowNumber
,DataMapID
,DataMapIDName
,DataMapGroup
,DataMapGroupRemark
,TimeStamp
From DataMapMain
WHERE
1 = 1'
+ @WhereString1
+ @WhereString2
+ ') DataMapMain
WHERE
RowNumber >= (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1) and RowNumber < (' + CONVERT(nvarchar(10),@StartIndex) + ' + 1 + ' + CONVERT(nvarchar(10),@MaximumRows) + ' )'
END
SET @params = '
@DataMapID VARCHAR(MAX)
,@DataMapIDName VARCHAR(MAX)
,@StartIndex INT
,@MaximumRows INT
,@sortExpression VARCHAR(MAX)';
EXEC sp_executesql
@SqlString
,@params
,@DataMapID
,@DataMapIDName
,@StartIndex
,@MaximumRows
,@sortExpression;
END