【问题标题】:SQL Injection Prevention in .NET.NET 中的 SQL 注入预防
【发布时间】:2012-11-20 23:40:59
【问题描述】:

我通常在 .NET 中编写我的 SQL

sql.Append("SELECT id, code, email FROM mytable WHERE variable = @variable ");

然后做这样的事情:

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["defaultConnection"]].ConnectionString))
{
    using (SqlCommand myCommand = new SqlCommand(sql.ToString(), conn))
    {
        myCommand.Parameters.AddWithValue("@variable", myVariableName");
        ...

但是当我得到的数据直接来自数据库时,我是否也应该这样做 addParameter 呢?

likesql.Append(string.Format("SELECT group_id, like_text FROM likeTerms ORDER BY group_id ASC "));

DataTable dtLike = SqlHelper.GetDataTable(likesql.ToString());

foreach (DataRow dr in dtLike)
{
    buildsql.Append(".... varId = " + dr["group_id"].ToString() + "...");

    ...

这可以接受吗?最佳做法是什么?

【问题讨论】:

    标签: c# .net sql ado.net


    【解决方案1】:

    您应该始终使用参数:

    • 数据库中的值来自哪里?
    • 您能相信,在您的示例中,“group_id”没有被修改为您不期望的东西吗?

    相信任何人

    数据库访问受限的人可以直接注入到其他地方使用的字段吗?

    性能

    此外,它有助于提高性能。缓存的执行计划将忽略参数的值,这意味着您无需在每次参数更改时重新编译查询。

    【讨论】:

    • 您需要为该观点提供一些理由,以使此答案在这里有任何好处。
    • 好多了,我正要提到执行计划的事情,但现在我不会打扰:)
    【解决方案2】:

    当您使用带参数的 DbCommands 时,参数永远不会“内联”到查询中。相反,查询和参数数据被传递到一个特殊的系统存储过程 sp_executesql。当它以这种方式完成时,您拥有的任何参数数据都将被视为完全一样,并且不会从查询字符串中解析出来;因此,可能已经通过验证的注入命令永远不会执行。

    使用参数是基于 ADO.NET 的数据访问层的最佳实践,无论数据来自何处,并且是 IMO 应该在此级别完成的唯一方法(如果您不使用 ORM )。您永远不应该将从 Web 或 Windows 表单中检索到的值连接到 SQL 语句中,如果您遵循该规则,为什么您会因为您有信心甚至确定信息不是直接的而以不同的方式实现它来自用户?遵循相同的模式,并且当您公开该方法以持久化用户指定的数据时,您将不会被烧毁。

    【讨论】:

    • 并没有真正解决 OP 的问题。他在谈论参数化来自数据库的值,而不是(直接)来自用户输入。
    • ORM 或对象关系映射器以某种形式获得信息,告诉它们如何在数据库表中的行之间转换或映射对象及其包含的任何子对象.然后,它们在 ADO.NET 中动态生成参数化查询。他们不关心他们处理的数据来自哪里(他们通常不知道);一切都作为参数传递到查询中,所以没有意外。
    【解决方案3】:

    这是可以接受的(从某种意义上说,如果您知道限制,您有时可能会正常工作)。

    使用数据库中的值并使用字符串连接构建 SQL 查询是一种好习惯 - 否。

    即在您的示例中,如果“group_id”是"'--",该怎么办?

    【讨论】:

    • 那么总是使用参数
    • 基本上。我的回答解释了原因,但他的回答又短又甜;攻击者仍然可以通过将命令注入正确参数化的查询来造成损害的方式非常少。通过将相同的数据连接到查询字符串中来造成损害的方式有很多种。
    • 我同意你的观点,但前提是 group_id 是数据库中的一个数字字段,顾名思义就是这样。这是因为像“'--”这样的东西不能来自 SQL 中的数字字段。如果它是一个文本字段,那么你就会遇到各种潜在的问题。
    • 是的,你们两个都是对的,但是从现在开始,无论数据来自哪里,我都将始终使用参数化 SQL。谢谢!
    【解决方案4】:

    我推荐使用存储过程,但这是可以接受的 我还建议您在将参数分配给查询之前对其进行清理

    【讨论】:

    • 为什么推荐存储过程?这不就是要维护的额外“代码”吗?
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2017-12-17
    • 2012-12-21
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多