Blog
- Home
- Entity Framework Core
- SQL Injection attacks in Entity Framework Core 2.0
SQL Injection attacks in Entity Framework Core 2.0
Using an ORM framework isn't enough to prevent you from attacks like SQL injections. You have to use the framework with good practices and avoid bad code.
Here are some (quick) highlights about good and bad practices using Entity Framework Core 2.0.
Using the FromSql()
Bad practice: using string concatenation
Good practice: using string interpolation
Using the ToSql()
With ToSql(), be careful about overloads
Nick Craver wrote some scenarios to illustrate the risk related to the overloads. The next samples are just excerpts of his work, which you can find here.
static class Program
{
static void Main(string[] args)
{
string param = args.Length > 0 ? args[0] : "'Hey' Name, 1 IsAdmin --";
using (var context = new TestContext())
{
WriteColor("This is parameterized, due to the FomattableString overload:");
WriteLine(context.Users.FromSql($"Select 1 UserId, {param} Name, 0 IsAdmin").ToSql());
}
}
}
static class Program
{
static void Main(string[] args)
{
string param = args.Length > 0 ? args[0] : "'Hey' Name, 1 IsAdmin --";
using (var context = new TestContext())
{
WriteColor("This is not parameterized, due to the var being string and using another overload:");
var sql = $"Select 1 UserId, {param} Name, 0 IsAdmin";
WriteLine(context.Users.FromSql(sql).ToSql());
}
}
}
static class Program
{
static void Main(string[] args)
{
string param = args.Length > 0 ? args[0] : "'Hey' Name, 1 IsAdmin --";
using (var context = new TestContext())
{
WriteColor("This is also not parameterized, due to string using another overload:");
string sqlString = $"Select 1 UserId, {param} Name, 0 IsAdmin";
WriteLine(context.Users.FromSql(sqlString).ToSql());
}
}
}
static class Program
{
static void Main(string[] args)
{
string param = args.Length > 0 ? args[0] : "'Hey' Name, 1 IsAdmin --";
using (var context = new TestContext())
{
WriteColor("This would appear to work, but is another injection path:");
string injectionParam = "'" + param;
string sqlQuotedString = $"Select 1 UserId, '{injectionParam}' Name, 0 IsAdmin";
WriteLine(context.Users.FromSql(sqlQuotedString).ToSql());
}
}
}
static class Program
{
static void Main(string[] args)
{
string param = args.Length > 0 ? args[0] : "'Hey' Name, 1 IsAdmin --";
using (var context = new TestContext())
{
WriteColor("This would appear to work, but is another injection path:");
string injectionName2 = "'" + param;
string quotedName = $"'{injectionName2}'";
string sqlStringQuotedName = $"Select 1 UserId, {quotedName} Name, 0 IsAdmin";
WriteLine(context.Users.FromSql(sqlStringQuotedName).ToSql());
}
}
}
That's it. Just a little post about a critical subject perfectly explained by the ASP.NET Monsters series, and brilliantly illustrated by Nick Craver.
November 21, 2017