SQL注入实体框架Database.SqlQuery

时间:2017-05-29 08:28:19

标签: c# sql-server asp.net-mvc entity-framework sql-injection

在我的项目中,我已经使用下面的示例代码定义了一个存储过程:

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阻止这种情况?

3 个答案:

答案 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结构,因此您不需要动态查询。