提问人:Ram 提问时间:9/18/2018 最后编辑:Ram 更新时间:9/18/2018 访问量:148
SQL Server 存储过程中的 SQL 注入
sql injection in sql server stored procedure
问:
在下面的过程中,如何检查参数 @TECHNOLOGY,@CURE,@APPLICATION 的 SQL 注入?请帮忙
CREATE PROCEDURE [dbo].[SEARCH]
@PRODUCTNAME NVARCHAR(500),
@TECHNOLOGY NVARCHAR(200),
@CURE NVARCHAR(200),
@APPLICATION NVARCHAR(200)
AS
SELECT DISTINCT PM.F_PRODUCT AS ID,
PM.F_PRODUCT_NAME AS [NAME],
PM.F_FORMAT AS FMT,
PM.F_SUBFORMAT AS SFMT,
STUFF((SELECT DISTINCT ', ' + CAST(F_LANGUAGE AS VARCHAR(200)) FROM T_PDF_MSDS PD
WHERE PD.F_PRODUCT = PM.F_PRODUCT AND PD.F_FORMAT = PM.F_FORMAT AND PD.F_SUBFORMAT = PM.F_SUBFORMAT
FOR XML PATH('')),1,1,'') AS LANG,
PM.F_DOC_PATH AS DPATH,
CONVERT(VARCHAR,PM.F_PUBLISHED_DATE,120) AS PDATE,
SUBSTRING(PM.F_CUSTOM1, CHARINDEX(':',PM.F_CUSTOM1)+1, LEN(PM.F_CUSTOM1)) AS TECHNOLOGY,
SUBSTRING(PM.F_CUSTOM2, CHARINDEX(':',PM.F_CUSTOM2)+1, LEN(PM.F_CUSTOM2)) AS CURE,
SUBSTRING(PM.F_CUSTOM3, CHARINDEX(':',PM.F_CUSTOM3)+1, LEN(PM.F_CUSTOM3)) AS [APPLICATION],
'PDF' AS DOC
FROM T_PDF_MSDS PM
WHERE
--(@PRODUCTNAME IS NULL OR REPLACE(REPLACE(REPLACE(REPLACE(PM.F_PRODUCT_NAME,'™','|TM'),'®','|TS'),'©','|CP'),'°','|DEG')
--LIKE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PRODUCTNAME,'[','\['),'_','\_'),'™','|TM'),'®','|TS'),'©','|CP'),'°','|DEG') ESCAPE '\')
(@TECHNOLOGY = '-1' OR PM.F_CUSTOM1 LIKE '%' + @TECHNOLOGY + '%')
AND (@CURE = '-1' OR PM.F_CUSTOM2 LIKE '%' + @CURE + '%')
AND (@APPLICATION = '-1' OR PM.F_CUSTOM3 LIKE '%' + @APPLICATION + '%')
AND PM.F_AUTHORIZED IN (-1,1,3)
GROUP BY PM.F_PRODUCT, PM.F_PRODUCT_NAME, PM.F_FORMAT, PM.F_SUBFORMAT, PM.F_DOC_PATH, PM.F_PUBLISHED_DATE, PM.F_CUSTOM1, PM.F_CUSTOM2, PM.F_CUSTOM3
;
在上述过程中是否可以进行任何SQL注入?
答:
3赞
freefaller
9/18/2018
#1
SQL 注入通常是使用未经审查的输入构建 SQL 命令时。例如。。。
var sql = "SELECT * FROM MYTABLE WHERE MYCOLUMN = " + txtInput.Text;
var cmd = new SqlCommand(sql);
...
通过使用存储过程,可以有效地保护自己免受这种情况的影响。
感谢 @DanGuzman 的评论,他指出 SQL 注入确实可以通过存储过程实现,如果您以错误的方式调用它......
var sql = "EXEC MySproc '" + txtInput.Text + "'";
var cmd = new SqlCommand(sql);
...
正确的方法是确保使用参数化命令,例如...
var cmd = new SqlCommand("MySproc", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@MyParam", SqlDbType.NVarChar, 200));
cmd.Parameters["@MyParam"].Value = txtInput.Text;
...
作为对 OP 评论的回应(我觉得这在原始问题的范围内)......
通过在存储过程中使用动态 SQL,也有可能成为 SQL 注入的受害者。例如。。。
CREATE PROCEDURE [dbo].[MySproc]
@MyParam NVARCHAR(200),
@MyParam2 INT
AS
BEGIN
DECLARE @SQL NVARCHAR(1000)
SET @SQL = N'SELECT * FROM [MyTable] WHERE [MyColumn] = ''' + @MyParam + N''''
EXEC sp_executesql @SQL
END
为了保护自己,您应该参数化您传递给 ...sp_executesql
DECLARE @SQL NVARCHAR(1000)
SET @SQL = N'SELECT * FROM [MyTable] WHERE [MyColumn] = @MyParamInner'
EXEC sp_executesql @SQL, N'@MyParamInner NVARCHAR(200)', @MyParam
请注意,不应在 where 子句上用引号将@MyParamInner
括起来,即使它是基于字符的变量
如果您有多个值要传递,您可以将其更新为类似...
DECLARE @SQL NVARCHAR(1000)
SET @SQL = N'SELECT * FROM [MyTable] WHERE [MyColumn] = @MyParamInner AND [MyColumn2] = @MyParam2Inner'
EXEC sp_executesql @SQL, N'@MyParamInner NVARCHAR(200), @MyParam2Inner INT', @MyParam, @MyParam2
评论
0赞
Dan Guzman
9/18/2018
确实,除非过程代码中存在动态 SQL,否则不可能在存储过程中注入 SQL。但是,应用程序仍必须使用参数化命令正确调用存储过程,以避免 SQL 注入的风险。
0赞
freefaller
9/18/2018
@Dan,我很想知道如何在不使用参数化命令或动态 SQL 的情况下调用存储过程并实现 SQL 注入?(诚实的问题)
2赞
Dan Guzman
9/18/2018
公平的问题。.我已经看到在共享数据访问层中以这种方式构建的 proc 调用。根据 API,可以指定 CommandType.StoredProcedure,以确保在单独传递的命令文本和参数中仅指定 proc 名称。var sql = "EXEC dbo.YourProc '" + txtInput.Text + "';";
0赞
freefaller
9/18/2018
公平的答案!我可以把它添加到我的答案中吗?
1赞
Dan Guzman
9/18/2018
我很高兴看到你改进了你的答案,并使用了强类型参数而不是太强类型!AddWithValue
评论