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

时间:2009-01-13 11:34:10

标签: c# linq sql-injection dynamic-linq

我在ASP.NET MVC应用程序中有一个表,我希望它可以排序(服务器端)并使用AJAX过滤。我希望它在其他地方使用起来相当容易,并且不想将排序和过滤硬编码到查询表达式中,所以我找到了一种动态构建表达式的方法,我找到的最好的方法是使用Dynamic LINQ 。

来自以下网址的用户输入直接插入动态Where或OrderBy。

/Orders?sortby=OrderID&order=desc&CustomerName=Microsoft

这会产生两个表达式:

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

虽然我明白它不会直接在数据库中抛出,并且在这里插入直接SQL不起作用,因为它无法反映到属性并且它是类型安全的所有,我想知道是否有更多人比我更有创意可以找到一种方法来利用它。我能想到的一个漏洞是可以对表中不可见的属性进行排序/过滤,但这并不是有害的,因为它们仍然无法显示,并且可以通过散列来防止它。

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

确定,谢谢:)

3 个答案:

答案 0 :(得分:10)

  

由于LINQ to SQL使用类型安全的数据模型类,因此默认情况下会受到SQL注入攻击的保护。 LINQ to SQL将根据基础数据类型自动编码值   (c)ScottGu

但是你仍然可以在那里得到“除以零”,因此建议处理所有意外异常并限制有效条目的长度,JIC

答案 1 :(得分:9)

嗯......我刚刚发现Dynamic 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));

我在那上写了blog post

答案 2 :(得分:8)

只是一个想法,但你看过ADO.NET数据服务吗?这提供了一个支持REST的API,就像上面一样,内置了许多标准的LINQ功能。

我无法想到一个兴趣动态的LINQ漏洞利用我的头脑,但如果这是我,我将至少白名单成员(OrderIDCustomerName等) - 但我可能直接写出Expression逻辑;如果你只支持直接属性,那就不是特别难了。

例如,这里是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