此查询是否存在SQL注入风险?如果是这样,我该如何避免呢?

时间:2012-02-09 09:56:37

标签: c# asp.net ado.net sql-injection parameterized

我通常创建参数化查询以避免SQL注入攻击。但是,我有这种特殊情况,我还没有完全做到这一点:

public DataSet getLiveAccountingDSByParameterAndValue(string parameter, string value)
{
    string sql = "select table_ref as Source, method as Method, sip_code as Code, " +
        " from view_accountandmissed " +
        " where " + parameter + " like @value " +
        " order by time DESC ";
    MySqlCommand cmd = commonDA.createCommand(sql);
    cmd.Parameters.Add("@value", MySqlDbType.String);
    cmd.Parameters["@value"].Value = "%" + value + "%";

    MySqlDataAdapter objDA = commonDA.createDataAdapter(cmd);
    DataSet objDS = new DataSet();
    objDA.Fill(objDS);
    return objDS;
}

正如您所看到的,我正在创建 @value 作为参数,但如果我尝试使用参数执行相同操作,则查询将失败。

那么,使用此查询是否存在SQL注入的风险?另外,请注意参数是由 DropDownList 的SelectedValue(不是TextBox,因此输入有限)设置的。如果是这样,我该如何改进此查询?

4 个答案:

答案 0 :(得分:4)

是的,有:

" where " + parameter + " like @value " +

参数中的值是您的风险。在回发中,您应检查所选值是否在下拉列表的起始值集中。

使参数成为枚举并将枚举传递给您的函数。这将消除风险(类似于:未经测试):

public DataSet getLiveAccountingDSByParameterAndValue(ParameterEnum parameter, string value)
.....
    " where " + parameter.ToString() + " like @value " +

ParameterEnum包含下拉列表中所有可能值的列表。在后面的代码中,将所选值解析为枚举。

答案 1 :(得分:2)

  

那么,使用此查询是否存在SQL注入的风险?

我认为是的,它容易受到SQL注入攻击。例如,参数 =“1 = 1 OR值”

  

另外,请考虑该参数由DropDownList设置   SelectedValue(不是TextBox,因此输入有限)

无关紧要。恶意用户可以在可执行文件本身或网络数据包上注入任何值(从而发送DropDown上不存在的值)。

  

如果是这样,我该如何改进此查询?

您应该检查参数参数并与DropDown值进行比较。对于更通用的数据,我认为应该有库来检查这些事情(但我没有C#的想法......)。

答案 2 :(得分:1)

var columns = new [] {"column1", column2", ....};
if (!columns.Contains(parameter))
   return or do something else

修改
唯一的SQL注入风险是使用字符串连接在where子句中传递列名。没有其他办法。真正的盾牌是检查列名是否有效,它存在于表中。
即使ASP .Net也有事件验证(检查发布的值是下拉列表之一),您不能以此为基础,因为可以禁用此保护。
与like一起使用的参数不是SQL注入的对象

答案 3 :(得分:1)

自2.0以来,ASP.NET自动验证回发和回调参数,以查看它们是否不同。因此,当EnableEventValidation对它有用时,这是一个很好的例子。

http://odetocode.com/blogs/scott/archive/2006/03/20/asp-net-event-validation-and-invalid-callback-or-postback-argument.aspx

您将获得以下异常:

  

“无效的回发或回调参数”

您可以通过在代码隐藏中明确设置它来确保将其设置为true,例如在Page的Init事件中:

protected void Page_Init( object sender, EventArgs e )
{
    // don't remove this
    Page.EnableEventValidation = True;
}

<击>

编辑:哎呀,实际上这个设置无法从代码隐藏中更改,它会编译但会在运行时错误后抛出:

  

'EnableEventValidation'属性只能在页面中设置   指令或在配置部分。