Entity Framework
Entity Framework is Microsoft's primary ORM (object-relational mapper) built on top of ADO.NET. There are currently two versions in use:
- Entity Framework 6, for .NET Framework
- Entity Framework Core, for .NET Core
In general, Entity Framework converts expression-based queries that use local variables:
// C# example
using (var ctx = new SchoolContext()) {
var firstname = "Robert'; DROP TABLE Students; --";
IQueryable<Student> qry = ctx.Students.Where(x => x.FirstName == firstname);
}
to queries with parameters:
-- SQL Server named parameter syntax
SELECT * FROM Students WHERE FirstName = @firstname
However, there are a number of places where EF allows writing raw SQL statements, and if parameters are not used, they are liable to be vulnerable to SQL injection:
EF6:
- DBSet.SqlQuery / DBSet<TEntity>.SqlQuery
- Database.SqlQuery / Database.SqlQuery<TEntity>
- Database.ExecuteSqlCommand
EF Core:
In order to use parameters with any of these methods:
- modify the SQL to use named placeholders1 with auto-generated names:
p0
,p1
,p2
. - pass the parameter values after the SQL
'ctx refers to an instance of a context class
Dim firstname = "Robert'; DROP TABLE Students; --"
Dim sql = "SELECT * FROM Students WHERE FirstName = @p0"
Dim qry = ctx.Students.SqlQuery(sql, firstname)
Alternatively, if you want to use named parameters1 in your SQL:
SELECT * FROM Students WHERE FirstName = @firstname
then you can pass in instances of the provider-specific parameter class:
'ctx refers to an instance of a context class
Dim sql = "SELECT * FROM Students WHERE FirstName = @p0"
Dim prm = New SqlParameter("@firstname", SqlDbType.NVarChar)
prm.Value = "Robert'; DROP TABLE Students; --"
Dim qry = ctx.Students.SqlQuery(sql, prm)
The above applies to both EF6 and EF Core. EF Core also allows passing the SQL as a format string together with the parameter values; format placeholders will be converted to parameters with the corresponding values:
// ctx refers to an instance of a context class
var firstname = "Robert'; DROP TABLE Students; --";
var qry = ctx.Students.FromSql("SELECT * FROM Students WHERE FirstName = {0}", firstname);
As of EF Core 2.0, EF Core also supports using interpolated strings; the interpolated strings will be converted to parameters:
// ctx refers to an instance of a context class
var firstname = "Robert'; DROP TABLE Students; --";
var qry = ctx.Students.FromSql($"SELECT * FROM Students WHERE FirstName = {firstname}");
Footnotes
1. Note that the syntax for named parameters can vary between providers.
References
- Entity Framework Raw SQL Queries
- Raw SQL for EF Core