【问题标题】:Is Injection Possible through Dynamic LINQ?是否可以通过动态 LINQ 进行注入?
【发布时间】:2012-02-03 01:37:48
【问题描述】:

使用动态 LINQ 库 (link),它是否容易受到注入?以及(如果是的话)如何防止这种情况发生?

来自Security Considerations (Entity Framework)的一些背景:

LINQ to Entities 注入攻击:

虽然查询组合在 LINQ to Entities 中是可能的,但它是 通过对象模型 API 执行。与实体 SQL 查询不同, LINQ to Entities 查询不是通过使用字符串操作组成的 或连接,它们不受传统 SQL 的影响 注入攻击。

既然动态 SQL 是使用字符串组成的,这是否意味着它可能容易受到注入向量的影响?还是 LINQ to SQL 会根据动态 LINQ 库中的基础数据类型自动处理您的值的参数化?

或者它是完全安全的,因为动态查询将在内存中执行而不是针对 SQL(从而否定 SQL 索引的任何好处)?

我一直在努力理解 DynamicLibrary.cs 代码,但我确信我很容易忽略一些东西。

由于此问题与动态 LINQ 库本身有关,因此可以认为此问题适用于 linq-to-sql 和 linq-to-entities(尽管上面提到了实体框架)。

【问题讨论】:

    标签: c# linq linq-to-sql linq-to-entities dynamic-linq


    【解决方案1】:

    好吧,我不同意在 Dynamic Linq 中无法进行注入。

    Ɖiamond ǤeezeƦ 在answer 中描述的内容是正确的,但适用于在给定语言(C# 或 VB.Net)内构建的标准 Linq,或者通过使用 lambda 函数调用 .Where 等扩展方法。

    那么,确实,不可能注入任何东西,因为 .NET Linq to Sql 转换器当然写得体面。 因此,“SQL注入”是不可能的,这是真的。

    但是,Dynamic Linq 可能发生的是“Linq injection”攻击。在OP引用的linq安全性解释中,指出:

    LINQ to Entities 查询不是使用字符串操作或连接组成的,它们不易受到传统 SQL 注入攻击。

    基本上这是一个要点。如果查询是由字符串操作组成的,那么它很容易受到注入攻击。而Dynamic Linq实际上是由字符串组成的,因此很容易受到注入攻击。

    显然,攻击者必须意识到您正在使用 DynamicLinq 并且只能攻击准备数据,因此它会导致有效的恶意 Dynamic Linq 查询。

    我想强调这个事实——最终的SQL是安全地组成的,但是原始的dynamic 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”(删除/更改数据/删除数据)事件隔离;也就是说,您可以使用 select 和 where 子句来更改数据库中的记录吗?
    • @Seph - 不,不可能更改记录,因为 linq 查询永远不会转换为更新、插入或删除 SQL。唯一可能的攻击可能是通过修改“where”过滤器来访问未经授权的数据。
    • @Seph - 无论如何,如果您使用占位符,正如我为所有用户输入所指出的那样,您就可以了。
    • @Krizz:当你需要类似 dataset.Where("allowed == 1 and code == \"" + user_entered_data + "\"");您可以改用它 -> dataset.Where("allowed == 1").where("code == \"" + user_entered_data + "\"");。第二个中的表达式 where call 将在括号中。因此,即使用户输入 OR 1=1 之类的内容,也不会在允许 1 的情况下为他提供此记录。我说的对吗?
    • @Cracker:您对具体示例没有错,但发现和/或避免并不总是那么简单。
    【解决方案2】:

    通过检查System.Data.Linq 命名空间,我了解到SQL 对象树是从LINQ 查询构建的,并且作为此过程的一部分,调用SqlParameterizer 类以将所有内联值替换为参数。然后将这些值分配给参数。所以 SQL 注入攻击应该是不可能的。

    【讨论】:

    • 对于 linq 通常是这样,但对于查询是字符串的动态 linq(OP 询问)不一定是这样,请参阅我的回答。
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 2012-11-02
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多