动态LINQ中的安全动态列名

时间:2014-02-05 16:18:03

标签: entity-framework linq-to-entities sql-injection dynamic-linq

我尝试使用LINQ创建动态WHERE子句。我有一个有效的例子,但我担心SQL注入不安全。

以下LINQ代码:

var oQuery = _db.People.Where("FirstName.Contains(@0)", "kev");

生成以下SQL:

SELECT 
[Extent1].[FirstName] AS [[FirstName], 
[Extent1].[LastName] AS [[LastName], 
WHERE [Extent1].[[FirstName] LIKE '%kev%'

这很好用,但现在我也想使用动态列名。所以我想我会做以下事情:

var oQuery = _db.People.Where("@0.Contains(@1)", strSelectedColumn,"kev");

但这会产生以下SQL:

  SELECT 
    [Extent1].[FirstName] AS [[FirstName], 
    [Extent1].[LastName] AS [[LastName], 
    WHERE N'FirstName' LIKE N'%kev%'}

这显然是错误的并且因为他正在比较2个字符串而得到0行。通过使用参数,LINQ可能只是在构建查询时将params作为字符串注入,而不是在构建期间使用有效的列名。

解决方案是使用以下LINQ查询:

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");

但是这会导致可能用于注入SQL的不安全SQL。

如何使用动态LINQ列并仍获得安全代码?

2 个答案:

答案 0 :(得分:1)

列名通常只包含字母,因此您可以对用户输入应用“哑”清理:

// user input: "abc';evil statement here"

strSelectedColumn = new string(strSelectedColumn.Where(c => char.IsLetter(c)).ToArray());
// abcevilstatementhere

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");

答案 1 :(得分:0)

这一行

var oQuery = _db.People.Where(strSelectedColumn + ".Contains(@0)", "kev");

生成安全的SQL代码,因为在生成SQL查询之前动态linq解析字符串表达式并创建表达式树。因此,如果在strSelectedColumn无效列中,则动态linq会在生成sql查询之前引发解析异常。

当你使用这个

var oQuery = _db.People.Where("@0.Contains(@1)", strSelectedColumn,"kev");

你得到了

WHERE N'FirstName' LIKE N'%kev%'

因为您没有检查字段的值,所以请尝试检查字符串参数的值。