不正确地中和 SQL 命令中使用的特殊元素(“SQL 注入”)

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

提问人:Alishba Jawaid 提问时间:7/26/2021 最后编辑:Peter CsalaAlishba Jawaid 更新时间:1/6/2023 访问量:1020

问:

我使用以下方法从我的应用程序调用存储过程,它运行良好。 主要问题是,当我在我的应用程序上运行veracode时,它给了我以下错误,ExecuteReader

“不正确地中和SQL命令中使用的特殊元素('SQL注入')”

解决该问题的参考如下,

“https://cwe.mitre.org/data/definitions/89.html”

如您所见,我的以下方法中没有静态查询,并且已经被调用以添加存储过程的参数。 我之前已经通过遵循静态查询参数的参考链接解决方案解决了这个错误,但是在下面的方法中没有涉及查询,所以我 我困惑如何解决它。Parameters.Add

谁能指导我解决此错误的解决方案?我不想更改调用存储过程的方法,因为它会影响我的整个生产应用程序。

public static List<Dictionary<string, object>> callProcForOutput(string procName, Dictionary<string, string> procParam, SqlConnection conn)
{
    List<Dictionary<string, object>> outvalues = new List<Dictionary<string, object>>();
    List<SqlParameter> parameters = new List<SqlParameter>();
    using (SqlCommand command = new SqlCommand(procName, conn))
    {
        procParam.ForEach(x => parameters.Add(new SqlParameter(x.Key, (object)x.Value)));

        command.CommandTimeout = 90;
        command.CommandType = CommandType.StoredProcedure;

        foreach (SqlParameter parameter in parameters)
        {
            command.Parameters.Add(parameter);
        }            

       
        command.Transaction = TransactionManager.TransManager.Transaction;

       
        SqlDataReader rdr = command.ExecuteReader();
        Dictionary<string, object> keyvalues = new Dictionary<string, object>();
        while (rdr.Read())
        {
            keyvalues = Enumerable.Range(0, rdr.FieldCount).ToDictionary(rdr.GetName, rdr.GetValue);
            outvalues.Add(keyvalues);
        }
        rdr.Close();
        return outvalues;
       
    }
}
C# ASP.NET-MVC ado.net SQL 注入 Veracode

评论

0赞 Martin 7/26/2021
如果这是被引用的代码,那么我看不到漏洞存在的位置。正如你所说,你正确地使用了参数化查询。
1赞 JonasH 7/26/2021
一个疯狂的猜测是,它不能证明不能注射。procName

答:

0赞 AC4 12/28/2022 #1

这是动态编码的一个很好的例子。但是,这种方法的基本灵活性是导致问题的原因。

了解扫描程序标记内容的一种方法是“要同步的源”。“源”通常是应过滤和验证的用户输入。“同步”也是输出数据的地方,通常是其他进程从(同步)的地方,通常是数据库。这是扫描程序希望看到控件和转义数据以保持持久性的地方。

该方法使用参数并调用变量这一事实可能会分散注意力,因为内容可以是任何函数过程,也可以是兼容的 SQLDDL。此外,在该方法的范围内,参数的名称不会被验证或过滤。在此方法的范围内,应将这些内容列入允许列表并进行转义。因此,标记此方法的简短原因是存储过程及其参数名称均不受限制。procName

如前所述,此方法允许调用任何语句。这种灵活性可以节省代码创建的工作量,在应用程序和数据库之间的边界上进行交互时,这种灵活性并不是最佳实践。这正是渗透测试人员试图检测和利用的功能。您希望控制可以调用哪些 SQL 和存储过程。如上所述,经常使用的一种模式是让单个函数包装单个查询或过程,因为它更安全。你可能会发现更灵活的模式,这些框架抽象了直接的 ADO .NET 调用,如 Dapper 或 Entity Framework。

另一种看待 C# 和安全性的方式就像是水一样。当你把水放在玻璃杯里时,它有表面张力,不仅在顶部,而且在它接触到任何东西的地方:玻璃杯、空气或你放在里面的勺子。这些是 C# 需要限制传入和传出的内容的地方。中间是您可以灵活而柔软的地方:D

我希望这种观点在解决这类问题时有所帮助,尤其是当自动化无法解释“为什么”时。