SQL 数据库备份的参数化查询被 sonarqube 报告为 sql 注入

SQL Parametrized query for database backup is reported as sql injection by sonarqube

我有几个 SQL SonarQube 报告的注入安全热点。我已更改我的实现以使用参数化查询,但问题尚未解决。 SonarQube 在以下行报告 SQL 注入:

SqlCommand cmd = new SqlCommand(cmdTxt, con);

我该如何解决?

String cmdTxt = String.Format(@"BAKUP DATABASE {0} TO DISK N'{1}'WITH FORMAT,COPY_ONLY,INIT, NAME ='{0} -Full Database Backup', SKIP", databasename, outputfile);

SqlCommand cmd = new SqlCommand(cmdTxt, con);

cmd.Parameters.Add("@database", SqlDbType.VarChar);

cmd.Parameters.Add("outputfile", SqlDbType.VarChar);

cmd.Parameters.["@database"].Value= database;

cmd.Parameters.["outputfile"] .Value= outfile;

Cmd.ExecuteNonQuery();

问题解决为:

 string sqlQuery = "DECLARE @sql nvarchar (max) = (" +
                                     "SELECT " +
                                     "'BACKUP DATABASE '" +
                                     "+ QUOTENAME(name) " +
                                     "+ ' TO DISK=@outputfile WITH FORMAT,COPY_ONLY,INIT, NAME = @backup_set_name_var, SKIP' " +
                                     "FROM sys.databases " +
                                     "WHERE name = @database); "+
                                     "EXEC sp_executesql " +
                                     "@sql, " +
                                     "N'@backup_set_name_var nvarchar(128), @outputfile nvarchar(128)', "+
                                     "@backup_set_name_var = @backup_set_name_var, "+
                                     "@outputfile = @outputfile; ";
                                     

            using (SqlCommand sqlCmd = new SqlCommand(sqlQuery , _sqlConnection))
            {
                sqlCmd.Parameters.Add("@database", SqlDbType.NVarChar, 128).Value = databaseName;
                sqlCmd.Parameters.Add("@backup_set_name_var", SqlDbType.NVarChar, 128).Value = databaseName + " -Full Database Backup";
                sqlCmd.Parameters.Add("@outputfile", SqlDbType.NVarChar, 128).Value = outputFile;

                sqlCmd.ExecuteNonQuery();
            }

很难说允许数据库名称作为参数本身是否危险。可以说是,但不一定是SQL注入

所以如果你想这样做,你可以传递它并创建一个经过验证的动态 SQL 语句(注意 using 块,并正确的参数类型和大小):

using(SqlCommand cmd = new SqlCommand(thebelowtext, con))
{
    cmd.Parameters.Add("@database", SqlDbType.NVarChar, 128).Value= database;
    cmd.Parameters.Add("@backup_set_name", SqlDbType.NVarChar, 128).Value= database + " -Full Database Backup";
    cmd.Parameters.Add("@outputfile", SqlDbType.NVarChar, 128).Value= outfile;

    cmd.ExecuteNonQuery();
}
DECLARE @sql = (
SELECT
    'BACKUP DATABASE '
    + QUOTENAME(name)
    + ' TO DISK=@outputfile WITH FORMAT,COPY_ONLY,INIT, NAME = @backup_set_name, SKIP'
FROM sys.databases
WHERE name = @database);

IF (@sql IS NULL)
    THROW 50000, N'Database does not exist', 0;

PRINT @sql;  --For testing in SSMS
EXEC sp_executesql
    @sql,
    N'@backup_set_name_var nvarchar(128), @outputfile nvarchar(128)',
    @backup_set_name = @backup_set_name,
    @outputfile = @outputfile;