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

问题描述 投票:2回答:4

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

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

但是,从理论上讲,不应该使用以下代码

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

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

  • qazxsw poi是我直接从DbContext模型获得的表名
  • table保证是一个idPair

?

我主要是因为我不知道是否应该禁止这个特定警告,或者尝试以另一种方式执行此操作(无论如何打开关于EntityFrameworkCore.Sqlite的错误报告都在待办事项列表中)。

c# .net .net-core
4个回答
3
投票

只要有问题的类型不能在生成的SQL中变成任何有害的东西,是的。请记住,一年后很容易找到这样的代码,却没有意识到实际上没有针对SQL注入的保护,并错误地添加了一些可能带来危险的东西。也许有人决定将所有密钥更改为字符串。关键是没有任何东西可以帮助你识别潜在的问题 - 没有编译器错误,没有运行时错误,一切都会像以前一样工作,直到有人滥用漏洞。也就是说,虽然你可以依靠KeyValuePair<int, int>永远不会包含任意int值的类型系统,但没有什么能保证string一年后仍然是idPair

而且,我永远不会说做坏事完全不可能。到目前为止,权衡通常偏向参数化查询,因为没有理由不使用它们。


8
投票

这不太可能导致问题,但在某些情况下,它可能也不完全安全。它正在使用当前的文化,这可能会带来一些令人讨厌的冲击。这是一个例子:

KeyValuePair<int, int>

输出:

using System;
using System.Collections.Generic;
using System.Globalization;

class Test
{
    static void Main()
    {
        // Imagine this somewhere entirely different
        var badCulture = (CultureInfo) CultureInfo.CurrentCulture.Clone();
        badCulture.NumberFormat.NegativeSign = "0 OR 1=1 OR Id=";        
        CultureInfo.CurrentCulture = badCulture;

        // Here's the code that looks innocent
        var idPair = new KeyValuePair<int, int>(-5, 10);
        string table = "Foo";
        string commandText = $"UPDATE {table} SET Id={idPair.Value} WHERE Id={idPair.Key};";

        Console.WriteLine(commandText);
    }
}

现在UPDATE Foo SET Id=10 WHERE Id=0 OR 1=1 OR Id=5; Id的所有行都被设置为10 ...

你可以强制使用不变的文化......但是我不确定它是否值得,说实话。

我强烈建议使用所有值的参数。我意识到你不能为表名这样做,并且没有好办法绕过它,但对于你可以和IMO应该使用参数的值。

除了其他任何事情,如果你试图在所有你认为安全的地方仔细地做这件事,那可以给人一种安全的印象,所以一个粗心的开发人员可以遵循相同的模式并使用字符串值,而不是注意安全。

有一些方法可以使用插值字符串文字和Foo来创建安全的参数化SQL,但是我看到的大多数代码都需要额外的调整才能让你也使用它来表名。


1
投票

我不确定你的意思是类型系统足够安全。但是你很容易在这里注入SQL。

如果FormattableString的价值是idPair.Key怎么办?您将在每条记录上更新Id到'anything' OR 'x'='x'

你应该做的是通过参数传递值参见这里:idPair.Value

这里的例子:

https://docs.microsoft.com/en-us/ef/core/querying/raw-sql

-1
投票

SQL注入攻击通常会暴露您的代码,因为传递给SQL的值来自用户输入。在您的情况下,您的代码将暴露给SQL注入,但验证传入的参数值(特别是如果不是由用户输入生成)将足以防止任何漏洞。

检查任何运算符符号和嵌入式引号,并拒绝具有它们的参数,或在嵌入变量之前主动转义这些符号。

© www.soinside.com 2019 - 2024. All rights reserved.