SQL 命令中使用的特殊元素的中和不当("SQL 注入")



我使用以下方法从我的应用程序调用存储过程,它工作得很好。主要问题是,当我在应用程序上运行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;

}
}

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

了解扫描仪正在标记什么的一种方法是根据"同步源"。"源"通常是需要过滤和验证的用户输入。'Sync'是数据输出的地方,通常是其他进程读取(同步)的地方,通常是数据库。这是扫描器期望看到的控件和为了持久化而转义的数据。

方法使用参数,变量名为procName,这一事实可能分散了内容可以是任何的事实。函数过程或兼容的SQLDDL。此外,在方法范围内,参数的名称为未验证或过滤。在这个方法的范围内,这些应该被允许列出和转义。因此,标记该方法的简单原因是存储过程及其参数名都不受限制。

如前所述,该方法允许调用任何语句。这种灵活性可以节省代码创建的工作量,但是当沿着应用程序和数据库之间的边界进行交互时,这种灵活性并不是最佳实践。这正是渗透测试者试图检测和利用的那种功能。您希望控制可以调用哪些SQL和存储过程。通常使用的一种模式是使用单个函数包装单个查询或过程,正如您上面提到的那样,因为这样更安全。你可能会发现更灵活的模式与框架抽象直接ADO . net调用,如Dapper或实体框架。 另一种看待c#和安全性的方式是把它看作是水。当你把水倒进杯子里时,它有表面张力,不仅在顶部,而且在它接触任何东西的地方:杯子,空气,或者你放进去的勺子。这些是c#需要限制输入和输出的地方。在中间是你变得灵活和柔软的地方:D

我希望这个观点在解决这类问题时有所帮助,特别是当自动化标记不善于解释"为什么"时。

最新更新