【问题标题】:Building a dynamic query in C# (SQL Injection Attack)用 C# 构建动态查询(SQL 注入攻击)
【发布时间】:2013-07-24 02:32:31
【问题描述】:

我有以下代码

public DataSet GetProject(string projectID)
{
   DataSet dataTable = new DataSet(); 
   DataAccess dataAccess = new DataAccess();
   OracleCommand commandOb = new OracleCommand();
   strQuery.Append("select projectName, managerName");
   strQuery.Append("from project ");
   strQuery.Append("where projectID = '" + projectID + "'");

   cmd.CommandText = strQuery.ToString();
   dataTable = dataAccess.ExecuteDataAdapter(commandOb);

   return dataTable;
}

这是构建和执行查询的好方法吗?这是否容易受到 SQL 注入攻击?

在动态构建查询时,是否有推荐的方法。任何帮助将不胜感激。

【问题讨论】:

  • Stay away from Dynamic querys 尝试使用参数化查询,如果你不熟悉如何做到这一点.. 然后使用string.Format(Select projectName,managerName from project where ProjectID={0}", projectID);
  • 使用参数化查询或者更好的是,调用存储过程...
  • +1 StoredProcedure 也不会出错
  • @DJKRAZE - 这对我来说看起来没有参数化......
  • 我说的没看懂。我说的是他不知道怎么做的。我非常了解如何编写参数化查询。我不会为他做 OP 的工作

标签: c# sql oracle code-injection enterprise


【解决方案1】:

以这种方式构建查询确实会使其容易受到 SQL 注入攻击,除非您手动转义了输入(即,“projectID”的值无法通过使用数据库引擎特定的转义序列来更改查询的结构) .但是,推荐的方法是使用参数化查询(有时称为“准备好的语句”)。使用参数化查询,您只需定义查询的结构,然后将输入值作为参数单独提供,从而防止您的查询结构通过 SQL 注入被更改。

这是你的例子,改为使用参数化:

public DataSet GetProject(string projectID)
{
   DataSet dataTable = new DataSet(); 
   DataAccess dataAccess = new DataAccess();
   OracleCommand commandOb = new OracleCommand();
   strQuery = @"select projectName, managerName
                  from project
                  where projectID = :ProjectID"

   cmd.CommandText = strQuery;
   cmd.Parameters.AddWithValue("ProjectID", projectID);
   dataTable = dataAccess.ExecuteDataAdapter(commandOb);

   return dataTable;
}

查询中的参数“:ProjectID”将替换为“AddWithValue”方法中给出的值。无论 'projectID' 变量中的值是什么,它都将始终作为 WHERE 子句的一部分进行评估。而之前,类似于 ['; DELETE FROM project;--] 通过将查询更改为如下内容可能会产生不良影响:

select projectName, managerName
  from project
  where projectID = ''; DELETE FROM project;--'

【讨论】:

    【解决方案2】:

    是的,该查询容易受到sql 注入的影响。如果projectID 是通过其他查询在您的应用程序内部检索到的,则它不太容易受到攻击,因为没有直接的用户输入。

    但是,如果是某些用户输入:"=1' OR 'a'=a'",则将检索所有项目,允许在未经适当授权的情况下访问数据。更糟糕的是,可能会执行非预期的命令,例如删除所有记录。

    不过,最佳做法是使用参数化查询或绑定参数以获得更好的性能和防止注入的安全性。参数化查询转义保留字符,但您仍然必须手写所有查询。替代方法包括使用 ORM 等。

    请参阅https://www.owasp.org/ 了解更多信息以及关于sql 注入的有用.net 特定博客系列等:http://www.troyhunt.com/2010/05/owasp-top-10-for-net-developers-part-1.html

    using (var cn = new OracleConnection(connString))
    {
      var sql = "select projectName, managerName from project where projectID = :p1";
      using (var cmd = new OracleCommand(sql, cn))
      {
        cmd.BindByName = true; 
        cmd.Parameters.Add(new OracleParameter(":p1", OracleDbType.Varchar2, projectID,
                                                ParameterDirection.Input));
        using (var adapter = new OracleDataAdapter(cmd))
        {
          cn.Open();
          var dataSet = new DataSet();
          adapter.Fill(dataSet);
          return dataSet;
        }
      }
    }
    

    注意:这是odp.net

    【讨论】:

      猜你喜欢
      • 2014-10-14
      • 2015-10-03
      • 2019-08-10
      • 1970-01-01
      • 2021-12-20
      • 2021-02-14
      • 2021-12-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多