【问题标题】:How do I prevent my SQL statements from SQL injection when using CLR/C++ with multiple variables?使用带有多个变量的 CLR/C++ 时,如何防止我的 SQL 语句被 SQL 注入?
【发布时间】:2020-05-15 03:27:44
【问题描述】:

我遇到了一个主要问题,在 CLR/C++ 中编写 SQL 语句时,我不知道如何防止 SQL 注入 下面是代码

String^ sqlstr = "SELECT * FROM ";
sqlstr += tableName + " WHERE " + field + " = " + fieldEntity;

我需要能够在此语句中输入正确的 SQL 注入预防措施。

后台代码

class database
{
protected:
    string fieldEntity;
    string tableName;
    string field;
...
____
OleDbDataReader^ openData(String^ fieldEntity, String^ field, String^ tableName)
    {

        String^ sqlstr = "SELECT * FROM ";
        sqlstr += tableName + " WHERE " + field + " = " + fieldEntity;
...
___
OleDbDataReader^ reader2 = testData.openData(effectID, "effectID", "effectOnUser");
    while (reader2->Read())
    {
        Object^ dHealthptr = reader2["effectOnHealth"];
        Object^ dTirednessptr = reader2["effectOnTiredness"];
        Object^ dHappinessptr = reader2["effectOnHappiness"];
...

【问题讨论】:

  • 参数化查询。
  • 我可以举一个简单的例子来说明如何使用 clr/c++ 应用到我的代码
  • 类似:"SELECT * FROM :table WHERE :field = :fieldEntity" 和绑定值
  • @Jarod42,不能将参数用于表名或列名。参数只能用于代替单个常量值——不能用于标识符、SQL 关键字、表达式、值列表等。
  • @LA 这个问题真的是关于“SQLCLR”(即使用 .NET 而不是 T-SQL 创建存储过程/函数等),还是关于执行 T-SQL 的 CLR / .NET 代码?

标签: sql visual-c++ clr sql-injection sqlclr


【解决方案1】:

有两种方法可以防止 SQL 注入,并且 SQLCLR 的环境不会改变这一点:

  1. 首选机制是使用参数化查询。不同的语言和库以不同的方式处理此问题,但至少您应该能够使用准备好的语句。 请注意,这不适用于不能接受变量的场景,例如在您的代码中使用 tableNamefield
    请参见:
    1. Issuing a Parameterized Query
    2. Using Stored Procedures
  2. 清理输入:

    1. 最低要求,也是迄今为止最常见的要求是通过将单引号加倍来转义单引号(即,' 变为 ''
    2. 另外(以下是我在 DBA.StackExchange 上的相关回答的引述):

      有一种鲜为人知的攻击类型,攻击者试图用撇号填充输入字段,这样存储过程中的字符串将用于构造动态 SQL,但被声明为太小。 t 适合所有内容并推出结束撇号并以某种方式以正确数量的撇号结束,以便不再在字符串中“转义”。这被称为 SQL 截断,并在 Bala Neerumalla 的题为“新 SQL 截断攻击和如何避免它们”的 MSDN 杂志文章中进行了讨论,但该文章已不再在线。包含本文的问题 — November, 2006 edition of MSDN Magazine — 仅作为 Windows 帮助文件(.chm 格式)提供。如果您下载它,它可能由于默认安全设置而无法打开。如果发生这种情况,请右键单击 MSDNMagazineNovember2006en-us.chm 文件并选择“属性”。在其中一个选项卡中,将有一个“信任这种类型的文件”(或类似的文件)选项,需要检查/启用。单击“确定”按钮,然后再次尝试打开 .chm 文件。

      因此,请务必正确调整字符串输入参数的大小。对于声明为 VARCHAR(25) 的列,您不需要 VARCHAR(500)。有关更多详细信息和示例,请参阅我在 DBA.StackExchange 上的回答: Why does SQL Injection not happen on this query inside a stored procedure?

【讨论】:

    【解决方案2】:

    对于tableNamefield 变量,它们在您的查询中用作SQL 标识符。您不能使用查询参数或转义的常用方法。您只需确保将这些变量的值列入白名单。换句话说,根据数据库中表和列的已知标识符检查它们。

    对于另一个变量fieldEntity,我想这应该像 SQL 查询中的常量值一样使用。您可以使用查询参数来保护它免受 SQL 注入。

    我不知道 CLR,但是有很多在 C++ 或 C# 中使用 SQL 查询参数的例子。

    【讨论】:

      猜你喜欢
      • 2021-05-01
      • 2018-08-16
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      • 2012-01-05
      • 2013-10-29
      • 2016-08-04
      相关资源
      最近更新 更多