直接用户输入的动态LINQ,有任何风险吗?

10
我在ASP.NET MVC应用程序中有一个表格,我希望能够使用AJAX进行排序(服务器端)和过滤。我希望它在其他地方也能够很容易地使用,不想将排序和过滤硬编码到查询表达式中,所以我寻找了一种动态构建表达式的方法,最好的方法是使用Dynamic LINQ。
用户从以下URL中输入的内容直接插入到动态Where或OrderBy中。
/Orders?sortby=OrderID&order=desc&CustomerName=Microsoft

这将导致两个表达式:

OrderBy("OrderID descending")
Where(@"CustomerName.Contains(""Microsoft"")")

我知道直接将 SQL 插入到这里不起作用,因为它不能被反射到属性上,而且它是类型安全的。虽然如此,如果有人比我更有创意,可能会找到一种利用它的方法。我能想到的一种利用方式是可以对不在表中可见的属性进行排序/过滤,但这并不会造成太大危害,因为它们仍然不会被显示,并且可以通过哈希来防止。

唯一允许直接用户输入的方式是使用 OrderBy 和 Where。

只是确保一下,谢谢 :)

3个回答

10
因为 LINQ to SQL 使用类型安全的数据模型类,所以默认情况下受到 SQL 注入攻击的保护。LINQ to SQL 将根据基础数据类型自动编码值。 (c)ScottGu
但是您仍然可能会遇到“除以零”错误,因此建议处理所有意外异常并限制有效输入的长度,以防万一。

9

嗯...我刚刚发现了动态Linq存在至少一个可能的问题。只需执行此代码片段1000次,观察CPU和内存消耗的增加(为拒绝服务攻击创建了一种简单的方式):

var lambda = DynamicExpression
  .ParseLambda<Order, bool>("Customer=string.Format(\"{0,9999999}"+
     "{0,9999999}{0,9999999}{0,9999999}{0,9999999}\",Customer)")
  .Compile();

var arg = new Order
{
  Total = 11
};
Console.WriteLine(lambda(arg));

我写了一篇与此相关的博客文章


1
我认为这是最相关的答案。 - Mark Rogers

8
只是一个想法,你是否看过ADO.NET数据服务?它提供了一个启用REST的API,与上述类似,并内置了许多标准LINQ功能。
我想不出一个有趣的动态LINQ利用方式,但如果是我的话,我至少会列出成员(OrderID、CustomerName等),但我可能会直接编写表达式逻辑;如果只支持直接属性,则并不特别困难。
例如,这里是Where(使用您的Contains逻辑):
static IQueryable<T> Where<T>(this IQueryable<T> source,
    string member, string value)
{
    var param = Expression.Parameter(typeof(T), "x");
    var arg = Expression.Constant(value, typeof(string));
    var prop = Expression.PropertyOrField(param, member);
    MethodInfo method = typeof(string).GetMethod(
        "Contains", new[] { typeof(string) });
    var invoke = Expression.Call(prop, method, arg);
    var lambda = Expression.Lambda<Func<T, bool>>(invoke, param);

    return source.Where(lambda);
}

我之前已经在这里介绍过OrderBy,链接在这里:previously, here


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