CS.SQL.INJECT.LOCAL

SQL 注入漏洞。如果 SQL 语句是使用未经验证的输入创建的,则恶意用户便可以通过攻击应用程序的特权而在此应用程序使用的数据库上注入字符串和执行任意 SQL 语句。

漏洞与风险

当代码输入未经妥善验证时,攻击者可以精心地将输入编制为允许攻击者执行任意 SQL 语句的格式。通过此类机会,攻击者可以:

  • 读取应用程序数据库中的机密数据;
  • 修改应用程序数据库中的数据;
  • 执行任意命令,如删除数据库中的所有信息。

要避免此问题,最好是:

  • 创建 SQL 语句时仅使用常数字符串;
  • 使用安全库创建将使用输入数据的参数化 SQL 语句;
  • 在使用 SQL 语句中的输入前,添加验证代码。

漏洞代码示例

复制
  public static void DeleteUser(string username, string connectionString)
  {
      using (SqlConnection connection = new SqlConnection(connectionString))
      {
          string sqlQuery = String.Format("DELETE FROM Users WHERE UserName='{0}'", username);
          SqlCommand command = new SqlCommand(sqlQuery, connection);
          command.Connection.Open();
          command.ExecuteNonQuery();
      }
  }

Klocwork 针对第 8 行生成了 SQL 注入报告,指出已将不安全的 SQL 查询字符串用作命令。在此情况下,可以使用输入“; DROP TABLE Users; --”进行 SQL 注入,该输入将删除数据库中的所有用户,而非仅删除具有完全匹配的用户名的用户。

修正代码示例

复制
  public static void DeleteUser(string username, string connectionString)
  {
      using (SqlConnection connection = new SqlConnection(connectionString))
      {
          string sqlQuery = "DELETE FROM Users WHERE UserName=@Username";
          SqlCommand command = new SqlCommand(sqlQuery, connection);
          command.Parameters.Add(new SqlParameter("@Username", username));
          command.Connection.Open();
          command.ExecuteNonQuery();
      }
  }

之前的代码段中出现的问题已修正:现在用户名用于通过安全库调用来创建 SQL 语句。该调用将验证输入并对其进行转换以防止 SQL 注入。