【问题标题】:SQL injection vulnerability veracode c#SQL注入漏洞veracode c#
【发布时间】:2020-08-21 00:25:59
【问题描述】:

Veracode 报告显示以下查询存在 SQL 注入缺陷。

private const string DropDatabaseTemplate = @"DROP DATABASE [{0}]";
ExecuteNonQuery(connection, string.Format(DropDatabaseTemplate, databaseName));

private static int ExecuteNonQuery(SqlConnection connection, string commandText)
        {
            using (var command = new SqlCommand(commandText, connection))
            {
                return command.ExecuteNonQuery();
            }
        }

他们建议使用参数化的预处理语句。 消除此安全漏洞的方法是什么

提前致谢。

回答: 您可以使用此方法轻松避免安全漏洞

 private static void ExecuteNonQuery(SqlConnection connection, string commandText)
        {
            using (var command = new SqlCommand("exec sp_executesql @sqlCommandText", connection))
            {
                command.Prepare();
                command.Parameters.Add("@sqlCommandText", SqlDbType.NVarChar);
                command.Parameters["@sqlCommandText"].Value = commandText;
                command.ExecuteNonQuery();
            }
        }

【问题讨论】:

  • 这能回答你的问题吗? How to give ADO.NET Parameters
  • 虽然此代码确实存在漏洞,但您无法对其进行参数化。在 SQL 中,您只能参数化数据,而不能参数化标识符。您唯一能做的就是在尝试删除数据库之前确保数据库确实存在 - 这是为了防止在发生异常时向用户泄露信息。
  • 该特定语句无法参数化,因此您收到的建议尽管总体上是正确的,但在这种情况下无法应用
  • 话虽如此,我建议不要在您的代码库中使用此方法选项。删除数据库应该是设计时操作,而不是运行时操作。顺便说一句,所有数据库结构更改都是如此。当然,也可能有不适用这条规则的情况,但这种情况很少。

标签: c# sql ado.net veracode secure-coding


【解决方案1】:

我从未尝试过,但我怀疑它会起作用:

    private static void DropDbNamed(SqlConnection connection, string name)
    {
        using (var command = new SqlCommand("EXEC @q", connection))
        {
            command.Parameters.AddWithValue("@q", $"DROP DATABASE [{name}]"); 
            var command.ExecuteScalar();
        }
    }

注意:Joel 的标准“停止使用 AddWithValue”不适用于此处

【讨论】:

    【解决方案2】:

    它会是什么样子。

    private const string DropDatabaseTemplate = @"DROP DATABASE [{0}]";
    
    
    private static int ExecuteNonQuery(SqlConnection connection, string commandText)
    {
        string dbNamesQuery_ = @"SELECT [name]
                    FROM sys.databases d
                    WHERE d.database_id > 4";
    
        DataTable tableNames = new DataTable();
        using (var command = new SqlCommand(dbNamesQuery_, connection))
        {
            SqlDataReader dataReader_ = command.ExecuteReader();
            tableNames.Load(dataReader_);        //allow you dynamically load actual list DB, but you can fill table manually.
            //find exactly same name of DB that user requared.
            var rowsData_ = tableNames.Select(String.Format("name = '{0}'", commandText));        
            if (rowsData_.Length == 1)        //it will be prevent any kind of injection.
            {
                command.CommandText = String.Format(DropDatabaseTemplate, commandText);
                return command.ExecuteNonQuery();
            }
            else
            {
                return -1;
            }
        }
    }
    

    【讨论】:

    • 为什么不简单地SELECT [name] FROM sys.databases WHERE [name] = @databaseName
    • @Zohar Peled 我相信“databaseName”可能是另一个存在漏洞的地方
    • 不是我写的参数。参数化查询可防止 SQL 注入。这是他们的主要观点。
    猜你喜欢
    • 1970-01-01
    • 2022-12-05
    • 2019-05-03
    • 1970-01-01
    • 2014-10-13
    • 2021-03-21
    • 2014-09-24
    • 1970-01-01
    • 2011-07-07
    相关资源
    最近更新 更多