flawopen.com/SQL Injection em C#/EF Core FromSqlRaw
O FromSqlRaw do Entity Framework Core é seguro?
Sim, se os valores permanecerem separados do texto SQL. FromSqlRaw aceita SQL bruto; concatenar ou interpolar uma entrada não confiável em sua string pode alterar a consulta. Use argumentos de parâmetros separados ou passe um FormattableString interpolado para FromSqlInterpolated (ou FromSql no EF Core 7+). Pense no parâmetro como um compartimento lacrado: o banco recebe o valor, não novas instruções SQL.
// A interpolação é avaliada primeiro como uma string. var sql = $"SELECT * FROM Users WHERE Id = {id}"; // FromSqlRaw recebe texto SQL, não um FormattableString. var query = context.Users.FromSqlRaw(sql);
// EF Core 3–6: placeholder posicional e valor separado. var byRawParameter = context.Users.FromSqlRaw( "SELECT * FROM Users WHERE Id = {0}", id); // EF Core 3+: passe a interpolação para a API parametrizada. var byInterpolation = context.Users.FromSqlInterpolated( $"SELECT * FROM Users WHERE Id = {id}"); // EF Core 7+: FromSql também recebe FormattableString. var byFromSql = context.Users.FromSql( $"SELECT * FROM Users WHERE Id = {id}");
O detalhe contraintuitivo
FromSqlInterpolated recebe um FormattableString. O EF Core lê o formato e os argumentos e envia cada valor interpolado como um parâmetro separado do banco; não há interceptação em tempo de compilação. O EF Core 7 adicionou FromSql com o mesmo comportamento seguro para strings interpoladas. Versões anteriores usam FromSqlInterpolated. FromSqlRaw também é seguro quando placeholders como {0} correspondem a valores passados em argumentos separados. Uma string interpolada armazenada primeiro como string já perdeu os metadados dos parâmetros.
Parâmetros vinculam valores, não nomes de colunas
Um parâmetro do banco representa um valor, não o nome de uma tabela ou coluna, um operador SQL ou a direção da ordenação. Se a estrutura da consulta precisar variar, escolha cada identificador de uma lista fixa permitida no código da aplicação; não tente parametrizar identificadores nem substitua essa lista por filtros de caracteres. Revise também autorização e custo da consulta: uma coluna válida ainda pode expor campos sensíveis ou provocar varreduras caras.
- ✓Para valores, use FromSqlInterpolated/FromSql com interpolação direta, ou FromSqlRaw com parâmetros separados.
- ✓Nunca passe dados concatenados ou interpolados do usuário para FromSqlRaw. Não converta primeiro um FormattableString em string.
- ✓Para identificadores dinâmicos, escolha itens de uma lista fixa permitida. Verifique separadamente a autorização e a existência de índices eficientes para o campo.
- ✓Prefira LINQ quando expressar a consulta com clareza; a parametrização impede injeção de sintaxe SQL, mas não aplica autorização nem regras de negócio.
Como revisar sua base de código
rg -n -g '*.cs' '(FromSqlRaw|FromSqlInterpolated|FromSql)\s*\(' .Perguntas frequentes
Sim, quando o SQL contém placeholders e os valores são passados como argumentos separados, por exemplo FromSqlRaw("... {0}", value). Não concatene nem interpole primeiro o valor na string SQL.
Ele recebe um FormattableString, que preserva o formato e os valores separadamente. O EF Core transforma cada valor em um parâmetro do banco. Se a interpolação for atribuída primeiro a uma string ou passada para FromSqlRaw, essa proteção se perde.
Não. Parâmetros representam somente valores. Para identificadores dinâmicos, mapeie as escolhas do usuário para uma lista fixa de identificadores conhecidos e revise autorização e custo da consulta.
Referências
- Microsoft Learn — consultas SQL e parametrização no EF Core
- Microsoft Learn — API FromSqlRaw
- Microsoft Learn — API FromSqlInterpolated
- OWASP — guia de prevenção de SQL Injection
- FlawOpen — SQL Injection em C#