c# - library - predicate builder net core
Dynamic LINQ con la entrada directa del usuario, cualquier peligro? (3)
Tengo una tabla en una aplicación ASP.NET MVC que quiero que se pueda ordenar (en el lado del servidor) y filtrar usando AJAX. Quería que fuera bastante fácil de usar en otros lugares y no tenía ganas de codificar de forma rígida la clasificación y el filtrado en expresiones de consulta, así que busqué la forma de construir las expresiones dinámicamente y la mejor forma de hacerlo fue con Dynamic LINQ .
La entrada del usuario desde una URL como la que se muestra a continuación se inserta directamente en un lugar dinámico donde u OrderBy.
/Orders?sortby=OrderID&order=desc&CustomerName=Microsoft
Esto daría como resultado dos expresiones:
OrderBy("OrderID descending")
Where(@"CustomerName.Contains(""Microsoft"")")
Aunque entiendo que no se lanzará directamente a la base de datos e insertar SQL directamente aquí no funcionará porque no se puede reflejar en una propiedad y es seguro para todos, y me pregunto si alguien más creativo que yo podría encontrar una forma de explotarlo independientemente. Un exploit que puedo pensar es que es posible ordenar / filtrar propiedades que no son visibles en la tabla, pero esto no es tan dañino ya que aún no se mostrarían y se puede evitar mediante hash.
La única manera de permitir la entrada directa del usuario es con OrderBy y Where.
Sólo asegúrate, gracias :)
Debido a que LINQ to SQL usa clases de modelos de datos seguros para el tipo, está protegido de ataques de Inyección SQL por defecto. LINQ to SQL codificará automáticamente los valores basados en el tipo de datos subyacente.
(c) ScottGu
Pero aún puede obtener "divide por cero" allí, por lo que se recomienda manejar todas las excepciones inesperadas y también limitar la longitud de las entradas válidas, JIC
Hum ... Acabo de encontrar al menos un problema posible con Dynamic Linq. Ejecute este fragmento 1000 veces y observe si la CPU y el consumo de memoria están en la parte superior (creando una forma fácil para el ataque de denegación de servicio):
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));
Escribí una publicación de blog sobre eso.
Solo un pensamiento, pero ¿ha mirado ADO.NET Data Services? Esto proporciona una API habilitada para REST muy similar a la anterior con una gran cantidad de funcionalidad LINQ estándar integrada.
No puedo pensar en un interés LINQ exploit de la parte superior de mi cabeza, pero si fuera yo estaría al menos en la lista blanca de miembros ( OrderID
, CustomerName
, etc.), pero probablemente escribiría la lógica Expression
directamente; no es especialmente difícil si solo estás apoyando propiedades directas.
Por ejemplo, aquí está Where
(usando su lógica 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);
}
He cubierto OrderBy
anteriormente, aquí .