动态LINQ是否存在注入漏洞?

50
使用动态LINQ库(link),它是否容易受到注入攻击?如果是,如何防范?
一些来自Security Considerations (Entity Framework)的背景信息:
LINQ to Entities注入攻击: 虽然在LINQ to Entities中可以进行查询组合,但是它是通过对象模型API执行的。与实体SQL查询不同,LINQ to Entities查询不是通过字符串操作或连接进行组合的,因此不容易受到传统的SQL注入攻击。
由于动态SQL是使用字符串组成的,这是否意味着它可能容易受到注入向量的攻击?或者,基于Dynamic LINQ库中的底层数据类型,LINQ to SQL是否会自动处理参数化值?
还是说它完全安全,因为动态查询将在内存中执行,而不是针对SQL(从而抵消了任何来自SQL索引的好处)?
我一直在努力理解 DynamicLibrary.cs 代码,但我肯定可能会轻易地忽略某些东西。
由于这个问题涉及到 Dynamic LINQ Library 本身,所以这个问题可以被认为适用于 linq-to-sql 和 linq-to-entities(尽管上面提到了 Entity Framework)。
2个回答

43

我并不同意在动态Linq中注入是不可能的。

答案中,Ɖiamond ǤeezeƦ所描述的确是正确的,但仅适用于在特定语言-如C#或VB.Net中构建的标准Linq或通过调用类似于带有lambda函数的.Where的扩展方法所生成的Linq。

因此,确实无法注入任何内容,因为.NET Linq to Sql转换器当然是很好编写的。因此,“SQL注入”是不可能的,这是事实。

但是,使用动态Linq可以进行“Linq注入”攻击。 在引用OP的链接中,对Linq安全性的解释如下:

LINQ到实体查询不是通过字符串操作或连接来组合的,也不容易受到传统SQL注入攻击。

这基本上是要点。 如果使用字符串操作来组合查询,则容易受到注入攻击。 而动态Linq实际上是由字符串组成的,因此可能容易受到注入攻击。

显然,攻击者必须知道您正在使用DynamicLinq,并且只能准备数据,使其产生有效的恶意Dynamic Linq查询。

我想强调这一点-最终的 SQL 安全地组成的,但原始的动态Linq是否安全取决于您

要使动态Linq查询安全,请为所有用户输入使用占位符。 不要将字符串连接在一起!

请想象以下查询:

dataset.Where("allowed == 1 and code == \"" + user_entered_data + "\"");

如果输入没有经过消毒和转义,攻击者可能会输入以下内容:


200" or allowed == 0 and code == "200

这将导致:

allowed == 1 and code == "200" or allowed == 0 and code == "200"
为了避免这种情况,您应该使用占位符:
dataset.Where("allowed == 1 and code == @0", user_entered_data);

DynamicLinq将会把占位符(在这个例子中是用户输入的数据)作为一个lambda参数(而不是将其拼接到查询中),并依赖于Linq-To-Entities(或者其他后端)来安全地转换为SQL。


因此,注入导致数据泄漏仍然是可能的,但您仍然与“Bobby Tables”(删除/更改/删除数据)事件隔离;也就是说,您能否通过选择和where子句来更改数据库中的记录? - Seph
4
@Seph - 不,无法修改记录,因为linq查询永远不会转换为更新、插入或删除SQL。唯一可能的攻击方式是通过修改“where”过滤器来获取未经授权的数据访问权限。 - Krizz
@Seph - 无论如何,如果你像我提到的那样对所有用户输入使用占位符,那么就没问题了。 - Krizz
@Krizz:当你需要像dataset.Where("allowed == 1 and code == "" + user_entered_data + """);这样的东西时,你可以使用这个代替 -> dataset.Where("allowed == 1").where("code == "" + user_entered_data + """);。第二个where调用中的表达式将在括号中。所以即使用户输入类似于OR 1=1这样的内容,也不会给他那些allowed <> 1的记录。我是对的吗? - Cracker
@Cracker:你说的这个例子确实没错,但有时候要发现并避免这种情况并不是那么简单。 - Flater

4
据我所知,从检查 System.Data.Linq 命名空间中得到的信息是,LINQ 查询构建了一个 SQL 对象树,在此过程中调用了 SqlParameterizer 类来将所有内联值替换为参数。然后将这些值分配给参数。因此,SQL 注入攻击不应该是可能的。

2
这通常适用于linq,但不一定适用于动态linq(OP所询问的),其中查询是字符串,请参见我的答案。 - Krizz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接