在我的项目中,我已经使用下面的示例代码定义了一个存储过程:
CREATE PROCEDURE [dbo].[Stored]
@ParameterA AS varchar(128),
@ParameterB AS varchar(128),
@ParameterC AS varchar(400)
AS
BEGIN
DECLARE @query AS Varchar(MAX)
SET @query = 'SELECT *
FROM Table
WHERE A = '''+ @ParameterA + ''
IF @ParameterB = 'B'
BEGIN
SET @query = @query + ' AND C=''' + @ParameterC + ''
END
EXECUTE sp_executesql @query
END
我通过以下代码使用Entity Framework调用此过程:
DBContext.Database.SqlQuery<Object>("Stored",
new SqlParameter("@p0", Param0),
new SqlParameter("@p1", Param1),
new SqlParameter("@p2", Param2)).ToList();
如果我用下面的字符串调用存储过程,我会生成一个SQL注入:
Param2 = "ABC' ; DROP TABLE Table2"
如何使用Entity Framework阻止这种情况?
答案 0 :(得分:2)
Microsoft提出了一些规则,以避免/最大限度地降低SQL注入的风险:https://docs.microsoft.com/en-us/sql/relational-databases/security/sql-injection
例如:
&#34;永远不要直接从用户输入构建Transact-SQL语句。&#34;
这意味着在这种情况下,我将使用参数化sp_executesql
重写原始代码:
CREATE PROCEDURE [dbo].[Stored]
@ParameterA AS varchar(128),
@ParameterB AS varchar(128),
@ParameterC AS varchar(400)
AS
BEGIN
DECLARE @query AS Varchar(MAX)
SET @query = 'SELECT *
FROM Table
WHERE A = @prmA'
IF @ParameterB = 'B'
BEGIN
SET @query = @query + ' AND C=@prmC'
END
EXECUTE sp_executesql @query, N'@prmA VARCHAR(128), @prmC VARCHAR(128)', @prmA = @ParameterA, @prmC = @ParameterC
END
sp_executesql的参考:https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql
答案 1 :(得分:1)
底层的SQL过程是错误的,是一个安全的噩梦。你无法在它上面的层上修复它。您在EntityFramework中尽了最大努力,但它仍然不安全。您需要修复问题(SQL proc),而不是使用它将带辅助工具应用到图层。
对于需要动态SQL和绑定参数的过程来说,sp_executesql似乎是一个很好的起点。
答案 2 :(得分:0)
您正在创建一个动态查询,您可以在其中连接参数。这引起了问题。
不要使用动态查询或验证参数(如果它包含任何关键字或字符)
您还可以根据参数将查询重写为IF-ELSE结构,因此您不需要动态查询。