My question
Can I avoid expressions being routed through WebAPI input parameters? Is it even possible for that to happen?
My situation (context)
I have some code very similar to this (this is a simplification to make the point clearer):
// DTO Classes:
public abstract class FilterableDtoBase<TEntity>
{
public string FilterValue { get; set; }
public abstract Expression<Func<TEntity, bool>> FilterExpression { get; }
public SortOrder SortOrder { get; set; } // Enum: SortOrder.Ascending, SortOrder.Descending
public abstract Expression<Func<TEntity, string>> OrderExpression { get; }
}
public class InvoiceByInvoiceNumberFilterableDto: FilterableDtoBase<Invoice>
{
public Expression<Func<Invoice, bool>> FilterExpression { get; } = i => i.InvoiceNumber.Contains(FilterValue);
public Expression<Func<Invoice, string>> OrderExpression { get; } => i => i.InvoiceNumber;
}
// In a web API controller class:
[HttpGet]
[Route("invoices/")]
public async Task<Invoice> GetInvoices([FromUri] InvoiceByInvoiceNumberFilterableDto request)
{
// Simulating EF: myDatamodel.Invoices is IQueryable<Invoice>
var results = myDatamodel.Invoices.Where(request.FilterExpression);
if (request.SortOrder == SortOrder.Ascending)
results = results.SortBy(request.OrderExpression);
else
results = results.SortByDescending(request.OrderExpression);
return results;
}
The objective behind this is two-fold:
- have the logic be reusable enough so that I can keep adding these through my code base without repeating too much for similar behavior
- allow consumers to have a consistent
FilterValue=x&SortOrder=Ascending
behavior.
However, as a result of this design, I realize that I'm passing lambdas that are constructed from requests DTOs directly into my model, the properties for the DTOs are exposed to Web API mapping as any other property.
The question:
Can an URI / Request body be constructed so that a consumer of the service can construct any lambda expression that they can use against me? I would like to know if this is something that WebAPI permits.
For example, could someone call http://example.com/invoices?FilterExpression=Expression.Call(MethodName=SQL,"DROP TABLE")...
, or an expression in any way like this giving the attacker control over my code?
If so, can I prevent certain properties from being routed by Web API?
Update: My objective is not to allow the client to submit expressions. My goal is to make sure this cannot happen so that I'm not exposing myself to a security problem. The expressions are just used to abstract filters from the different entities in the system.