C#/.NET (Core):类型系统是否足够安全以防止 SQL 注入?

我正在开发一个使用 EF Core 的项目;在一种特定情况下,我必须使用原始 SQLite 命令更新实体的身份。

构建一个 SqlCommand 并执行它由于某种原因不起作用,以及直接将参数传递给ExecuteSqlCommand(),它总是抛出一个异常(我猜这是当前 Sqlite 驱动程序中的一个错误)。

但是,理论上,不应该下面的代码

string commandText = $"UPDATE {table} SET Id={idPair.Value} WHERE Id={idPair.Key};";

已经阻止了 SQL 注入,因为这里

  • table 是我直接从 DbContext 的模型中获得的表名

  • idPair 是一个保证是 KeyValuePair<int, int>

?

我主要是在问,因为我不知道是否应该取消此特定警告,或者尝试以其他方式执行此操作(无论如何,在 EntityFrameworkCore.Sqlite 上打开错误报告都在待办事项列表中)。


长风秋雁
浏览 529回答 3
3回答

倚天杖

它不太可能引起问题,但在某些情况下也可能不完全安全。它正在使用当前的文化,这可能会带来一些令人讨厌的冲击。这是一个例子:using System;using System.Collections.Generic;using System.Globalization;class Test{&nbsp; &nbsp; static void Main()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Imagine this somewhere entirely different&nbsp; &nbsp; &nbsp; &nbsp; var badCulture = (CultureInfo) CultureInfo.CurrentCulture.Clone();&nbsp; &nbsp; &nbsp; &nbsp; badCulture.NumberFormat.NegativeSign = "0 OR 1=1 OR Id=";&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; CultureInfo.CurrentCulture = badCulture;&nbsp; &nbsp; &nbsp; &nbsp; // Here's the code that looks innocent&nbsp; &nbsp; &nbsp; &nbsp; var idPair = new KeyValuePair<int, int>(-5, 10);&nbsp; &nbsp; &nbsp; &nbsp; string table = "Foo";&nbsp; &nbsp; &nbsp; &nbsp; string commandText = $"UPDATE {table} SET Id={idPair.Value} WHERE Id={idPair.Key};";&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(commandText);&nbsp; &nbsp; }}输出:UPDATE Foo SET Id=10 WHERE Id=0 OR 1=1 OR Id=5;现在为...Id中的所有行设置为 10Foo你可以强制使用不变的文化......但老实说,我不确定它是否值得。我强烈建议对所有值使用参数。我意识到您不能为表名这样做,并且没有好的方法可以解决这个问题,但是对于您可以的值,IMO应该使用参数。除此之外,如果您尝试在所有您知道它是安全的地方仔细执行此操作,那么可能会给人一种它总是安全的印象,因此粗心的开发人员可能会遵循相同的模式并将其与字符串值一起使用注意安全。有多种方法可以使用插值字符串文字FormattableString来创建安全的参数化 SQL,但我看到的大多数代码都需要额外的调整,以便您也可以将其用于表名。

忽然笑

只要有问题的类型不能在生成的 SQL 中变成任何有害的东西,就可以。请记住,一年后很容易得到这样的代码,却没有意识到实际上没有针对 SQL 注入的保护,并且错误地添加了一些可能很危险的东西。也许有人决定将您所有的键更改为字符串。关键是没有任何东西可以帮助您识别潜在问题 - 没有编译器错误,没有运行时错误,一切都会像以前一样正常工作,直到有人滥用这个漏洞。也就是说,虽然您可以依赖 anint永远不会包含任意string值的类型系统,但无法保证一年后idPair仍会如此。KeyValuePair<int, int>另外,我永远不会说做坏事是绝对不可能的。到目前为止,权衡通常偏向于参数化查询,因此几乎没有理由不使用它们。

拉丁的传说

我不确定你的意思是类型系统足够安全。但是你在这里很容易受到 SQL 注入的攻击。ifidPair.Key的值是'anything' OR 'x'='x'什么?您将idPair.Value在每条记录上更新 ID。您应该做的是通过参数传递值,请参见此处:https ://docs.microsoft.com/en-us/ef/core/querying/raw-sql这里的例子:context.Blogs&nbsp; &nbsp; .FromSql("EXECUTE dbo.GetMostPopularBlogsForUser {0}", user)&nbsp; &nbsp; .ToList();
打开App,查看更多内容
随时随地看视频慕课网APP