无法使用FormattableString

时间:2019-07-19 09:16:39

标签: .net-core formattablestring

通过阅读this interesting article有关EF Core中的SQL注入预防的知识,我发现现在插入的字符串可能会导致FormattableString

在.NET Core 2.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

第二张打印输出应该与上一张打印一样。

尝试使用fiddle

我想念什么?

1 个答案:

答案 0 :(得分:0)

您的第二个呼叫Console.WriteLine(FromSql($"SELECT * FROM tbl WHERE fld = {filter}"));似乎将导致FromSql(string sql)重载,而不是FromSql(FormattableString sql)

只需删除FromSql(string sql)方法(及其第一个调用)
它将按预期进行;请参阅修改后的Fiddle


编译器似乎要翻译 var q = $"SELECT * FROM tbl WHERE fld = {filter}";string

 String q = $"SELECT * FROM tbl WHERE fld = {filter}";`  

由于类型为string,所以发生了String.Format
来自documentation

  

如果插值字符串的类型为 string ,则通常会将其转换为 String.Format 方法调用。


一样,明确指定FormattableString
FormattableString q = $"SELECT * FROM tbl WHERE fld = {filter}";  

正在使用FormattableStringFactory.Create
来自documentation

  

如果插值字符串的类型为IFormattable或 FormattableString ,则编译器将生成对 FormattableStringFactory.Create 方法的调用。