sql 在 sql 服务器存储过程中注入
sql injection in sql server stored procedure
在我下面的程序中,如何检查 SQL 注入参数 @TECHNOLOGY、@CURE、@APPLICATION?请帮忙
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 注射?
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
在我下面的程序中,如何检查 SQL 注入参数 @TECHNOLOGY、@CURE、@APPLICATION?请帮忙
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 注射?
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