这是一个漏洞的抽象吗?

时间:2009-02-28 02:00:14

标签: coding-style

在中间层指定一个漏洞抽象的字段名称?

我觉得为每个字段创建一个单独的函数太麻烦了,即使它是代码生成的。

        public bool Assortment_IsValueExistingOnOtherRecord(
            Dictionary<string, object> exceptPkColumns,
            string field, object value
            )
        {
            var c = Connect();

            var dt = new DataTable();

            string sanitizedField = field.Replace("'","");

            var daAssortment = new SqlDataAdapter(
               string.Format(
@"SELECT 1 FROM assortment
WHERE 
/* do I violate any good programming practice here? */ [{0}] = @value 
AND NOT (assortment_id = @assortment_id)",  field), c);

            daAssortment.SelectCommand.Parameters.Add("assortment_id", exceptPkColumns["assortment_id"]);
            daAssortment.SelectCommand.Parameters.Add("value", value);
            daAssortment.Fill(dt);

            return dt.Rows.Count == 1;
        } 

4 个答案:

答案 0 :(得分:1)

[{0}] = @value

只要采取适当的措施,这是好的。 “消毒”不属于这些措施之中。

选项1:你是否对该领域的提供者有一种隐含的信任,这样你才知道他们永远不会惹你生气?例如,如果您(作为此模块的作者)是该字段的提供者,您可以相信自己。

选项2:你能创建一个将请求的字段映射到字符串的枚举/查找吗?然后,此代码的“客户端”只能请求枚举中的内容,并且您(此模块的作者)通过将其请求的枚举值映射到已知字符串而成为字段提供者。

选项3:如果字段随时间变化并且您不想使用枚举锁定,是否可以将字符串值发送到数据库进行确认?

SELECT name
FROM syscolumns
WHERE name = @name

这会将提供的名称映射到来自数据库的已知字符串,并且必须是安全的。

答案 1 :(得分:1)

从封装的角度来看,你所写的内容并没有错。

然而,正如“大卫B”提到的那样(他对此有点担心),你需要注意一些安全问题。

您生成的动态SQL受到称为“SQL注入攻击”的影响。例如,想象一下,field的值是以下字符串:

assortment_id] = 0 and assortment_id = 1 
delete from assortment
select 1 from assortment where [assortment_id

这将导致数据库执行3个查询:

  1. 无效结果的虚拟选择查询
  2. 删除分类表中所有内容的删除查询
  3. 真正的选择查询
  4. 显然,这可能会导致一些问题。

    如果通过以下方式指定“field”的值:

    1. 用户界面字段
    2. 网页表单提交
    3. 来自网络服务客户端
    4. 从磁盘上的文件加载
    5. 或者除了代码
    6. 中提供的常量值以外的任何其他方式

      然后,您需要在运行任何查询之前验证数据以确保它是有效的字段值。否则你很容易受到攻击。

答案 2 :(得分:0)

使用表达式,您将拥有编译时(和Sql运行时)的安全性:

public bool Assortment_IsValueExistingOnOtherRecord<TValue>(
        Dictionary<string, object> exceptPks,
        Expression<Func<Assortment, TValue>> expression,
        TValue value
        )

    propExp = expression.Body as MemberExpression;
    if (propExp == null) throw new ArgumentException();
    string field = propExp.Member.Name; 

    /* blah, blah */
}

/* Calling code */
bool exists = Assortment_IsValueExistingOnOtherRecord(
                exceptPKs, 
                (a => a.Property1),
                "property1Value"
              );

使用通用TValue,您还可以获得与属性匹配的强类型值 - 避免RDBMS偶尔为您做的脑死亡。

你可以拥有整个equals表达式,甚至可以添加对&lt;的支持。和&gt; - 但是,你只是在发明LINQ到本土的ORM。 ;)

顺便说一下,exceptPK似乎有点奇怪......但也许它在上下文中有意义?

答案 3 :(得分:0)

是。所有的抽象都泄漏了。

现在,就安全性而言,如果您没有明确地信任所有呼叫者不要愚蠢(或寻求主动攻击您),您最好拥有所有可能字段的emum并根据该列表验证传入参数。