Um dos novos recursos do Entity Framework Core 2 é a possibilidade de converter automaticamente strings interpoladas em script SQL parametrizado. Apesar da funcionalidade ter sido criada para evitar problemas com scripts SQL mal escritos, o medo é de que esse recurso possa ser utilizado para aumentar ataques de injeção de SQL.
Aqui, um exemplo de interpolação de strings funcionando corretamente:
var city = "Redmond";
context.Customers.FromSql($"SELECT * FROM Customers WHERE City = {city}");
SELECT * FROM Customers WHERE City = @p0
E aqui uma versão com uma pequena variação que não funciona:
var city = "Redmond";
var sql = $"SELECT * FROM Customers WHERE City = {city}";
context.Customers.FromSql(sql);
SELECT * FROM Customers WHERE City = Redmond
O simples fato de armazenar uma expressão em uma variável local muda completamente o comportamento do código.
Para entender porque isso acontece precisamos entender o que $" realmente faz no C#. Num primeiro momento, parece que é apenas uma conversão de string interpolada em uma simples chamada String.Format. Mas há um pouco mais do que isso.
O tipo natural de uma expressão $" é, na verdade, uma subclasse de FormattableString. Este objeto contém a expressão de formatação string e todos os valores necessários para populá-la. Ao passar o objeto para o método FromSql(FormattableString) do EF Core, são executadas as substituições necessárias para retornar a expressão SQL parametrizada.
O problema é que o compilador não gosta de trabalhar com FormattableString. A não ser que se atribua a expressão $" diretamente a uma variável ou parâmetro daquele tipo, a mesma será imediatamente convertida em uma string. Na maioria das vezes é uma mudança benéfica, uma vez que eventualmente queremos uma string.
Infelizmente, no caso do EF Core, perdemos toda informação que permite o Entity Framework parametrizar a expressão SQL. E sem os avisos (warinings) do compilador, ou outras sugestões que algo deu errado, este tipo de bug pode facilmente se tornar parte de uma aplicação conforme os desenvolvedores "limpam" o código.
Para mais exemplos de como enganos no uso da interpolação de string no EF Core pode causar ataques de injeção SQL, você pode fazer o download do EFCoreInjectionSample do Nick Craver a partir do GitHub, ou assista sua apresentação no ASP.NET monsters entitulada SQL Injection attacks in Entity Framework Core 2.0.