从 Entity Framework 核心访问 SQL 存储过程的安全方式
Secure way of accessing SQL Stored Procedures from Entity Framework Core
我正在 'Pen Test' 并试图找到 "most secure" 方法来使用 Entity Framework Core
存储过程。您可能认为这很明显,但请继续阅读。
背景
使用 this document on using Raw SQL and having read Whats new in .NET Core 2.0 我的初始代码使用字符串插值(在“新功能”文档中显示为安全)。
但是,Pen Test 成功地对其进行了 sql 注入攻击。
违规代码示例:
dbResults = _datacontext.Blogs.FromSql($"myStoredProcedure @parmeter1 = {parmeter1String}");
于是,我把代码改成使用params,结果他们也突破了这个:
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String);
他们打破了这个(虽然也许我清理得不够 - 至少我停止了 exec
):
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String.ToCleanedSqlString());
那么答案是使用 SqlParameter(上面没有显示docs/examples)吗?
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", new SqlParameter("@parmeter1", parmeter1String));
或者有更好的方法吗?
请提供一些明确的指导。
编辑以下评论:
重要补充:存储过程确实执行动态 sql,但该过程不在我的应用程序中,我无法控制它。我必须调用它。
在评论之后,我想我应该添加一个结论(感谢 @AlexK 通过评论)。
如果使用非参数化动态 sql 编写存储过程,Entity Framework 无法保护它。这不是 Entity Framework 的错误(一般来说,它在 sql 保护方面非常出色)。
如果您发现自己处于类似情况,则应使用参数化动态 sql 重新编写存储过程。可以找到很好的解释here.
详细说明。
Entity Framework没办法像这样保护sql:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE ''' + @custid + ''''
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE ''' + @shipname + ''''
EXEC(@sql)
但这会很安全:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE @custid '
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE @shipname '
EXEC sp_executesql @sql, N'@custid nchar(5), @shipname nvarchar(40)',
@custid, @shipname
据我所知,问题中的任何代码示例都是有效的 'safe' EF 代码(尽管扩展方法的额外工作超出了要求)。
更新
在此之后,我联系了 Microsoft 并创建了一个 PR, the basis of which has been accepted. The warning message on the official documentation is now more detailed,希望能减少有人遇到同样问题的机会。
我正在 'Pen Test' 并试图找到 "most secure" 方法来使用 Entity Framework Core
存储过程。您可能认为这很明显,但请继续阅读。
背景
使用 this document on using Raw SQL and having read Whats new in .NET Core 2.0 我的初始代码使用字符串插值(在“新功能”文档中显示为安全)。
但是,Pen Test 成功地对其进行了 sql 注入攻击。
违规代码示例:
dbResults = _datacontext.Blogs.FromSql($"myStoredProcedure @parmeter1 = {parmeter1String}");
于是,我把代码改成使用params,结果他们也突破了这个:
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String);
他们打破了这个(虽然也许我清理得不够 - 至少我停止了 exec
):
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", parmeter1String.ToCleanedSqlString());
那么答案是使用 SqlParameter(上面没有显示docs/examples)吗?
dbResults = _datacontext.Blogs.FromSql("myStoredProcedure @parmeter1 = {0}", new SqlParameter("@parmeter1", parmeter1String));
或者有更好的方法吗?
请提供一些明确的指导。
编辑以下评论:
重要补充:存储过程确实执行动态 sql,但该过程不在我的应用程序中,我无法控制它。我必须调用它。
在评论之后,我想我应该添加一个结论(感谢 @AlexK 通过评论)。
如果使用非参数化动态 sql 编写存储过程,Entity Framework 无法保护它。这不是 Entity Framework 的错误(一般来说,它在 sql 保护方面非常出色)。
如果您发现自己处于类似情况,则应使用参数化动态 sql 重新编写存储过程。可以找到很好的解释here.
详细说明。
Entity Framework没办法像这样保护sql:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE ''' + @custid + ''''
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE ''' + @shipname + ''''
EXEC(@sql)
但这会很安全:
CREATE PROCEDURE search_orders @custid nchar(5) = NULL,
@shipname nvarchar(40) = NULL AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ' SELECT OrderID, OrderDate, CustomerID, ShipName ' +
' FROM dbo.Orders WHERE 1 = 1 '
IF @custid IS NOT NULL
SELECT @sql = @sql + ' AND CustomerID LIKE @custid '
IF @shipname IS NOT NULL
SELECT @sql = @sql + ' AND ShipName LIKE @shipname '
EXEC sp_executesql @sql, N'@custid nchar(5), @shipname nvarchar(40)',
@custid, @shipname
据我所知,问题中的任何代码示例都是有效的 'safe' EF 代码(尽管扩展方法的额外工作超出了要求)。
更新
在此之后,我联系了 Microsoft 并创建了一个 PR, the basis of which has been accepted. The warning message on the official documentation is now more detailed,希望能减少有人遇到同样问题的机会。