在C#中构建动态查询(SQL注入攻击)

时间:2013-07-24 02:32:31

标签: c# sql oracle code-injection enterprise

我有以下代码

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注入攻击造成影响吗?

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

2 个答案:

答案 0 :(得分:3)

以这种方式构建查询会使其容易受到SQL注入攻击,除非您手动转义输入(IE使'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;--'

答案 1 :(得分:0)

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

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

尽管如此,最佳做法是使用参数化查询或绑定参数以获得更好的性能和注入安全性。参数化查询会转义保留字符,但您仍然需要手写出所有查询。替代方案包括使用ORM等。

有关.net注入的更多信息和有用的sql特定博客系列,请参阅https://www.owasp.org/,以及更多: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