通过阅读这篇有趣的文章有关EF中SQL注入预防的内容,我发现现在插入的字符串可能会导致FormattableString。
在.NET Core2.2中运行此测试代码:
public static void Main()
{
var filter = "Mark'; DROP TABLE tbl; --";
Console.WriteLine(FromSql("SELECT * FROM tbl WHERE fld = '" + filter + "'"));
Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));
Console.WriteLine(FromSql(FormattableStringFactory.Create(
"SELECT * FROM tbl WHERE fld = {0}", filter)));
}
private static string FromSql(string sql) => sql;
private static string FromSql(FormattableString sql)
{
var formatArgs = sql.GetArguments();
for (var paramIndex = 0; paramIndex < sql.ArgumentCount; ++paramIndex)
formatArgs[paramIndex] = "@p" + paramIndex;
return sql.ToString();
}不是我期望的那样:
SELECT * FROM tbl WHERE fld = 'Mark'; DROP TABLE tbl; --'
SELECT * FROM tbl WHERE fld = Mark'; DROP TABLE tbl; --
SELECT * FROM tbl WHERE fld = @p0第二个打印输出应该和最后一个输出一样。
试试看我是小提琴。
我遗漏了什么?
发布于 2019-07-19 21:01:02
您的第二个调用Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));看起来是FromSql(string sql)重载,而不是FromSql(FormattableString sql)。
只需删除FromSql(string sql)方法(以及对它的第一次调用),
它将如预期的那样进行;请参见修改后的小提琴。
编译器似乎将var q = $"SELECT * FROM tbl WHERE fld = {filter}";转换为string。
String q = $"SELECT * FROM tbl WHERE fld = {filter}";` 由于string类型,出现了一个String.Format。
来自文档
如果内插字符串的类型为String.Format字符串,则通常将其转换为方法调用。
而显式将FormattableString指定为
FormattableString q = $"SELECT * FROM tbl WHERE fld = {filter}"; 正在使用FormattableStringFactory.Create。
来自文档
如果内插字符串的类型为FormattableString,或IFormattable,则编译器将生成对FormattableStringFactory.Create方法的调用。
https://stackoverflow.com/questions/57109289
复制相似问题