我必须将一个SQL字符串注入数据库,供第三方读取,执行,并使用结果进行报告。由于用户可以选择报告所需的列,以及重命名列,因此我最终得到了这样的代码:
string sql = "SELECT ";
foreach(KeyValuePair<string, string> field in report.fields)
{
sql += "[" + field.Key + "] as [" + field.Value + "];
}
sql += " WHERE idrpt=@id";
我可以参数化的这个查询的唯一部分是WHERE子句,但是如果我在网上的研究没有被误导,那么就无法在SELECT子句中对列名和别名进行参数化。现在,鉴于我无法改变程序的工作方式(我必须向第三方生成有效的SQL查询来执行它),那么清理输入字符串的最佳方法是什么?
我已经通过在有效列列表中检查它们来解决有关列名的部分,但我不能为别名做到这一点,别名可以是用户愿意给出的少于80个字符的字符串。
答案 0 :(得分:1)
如您所述,无法对列名和别名进行参数化。因此,您打开SQL注入。为了最大限度地减少问题,您可以使用quotename,这与您当前使用的方法类似。
string sql = "SELECT ";
foreach(KeyValuePair<string, string> field in report.fields)
{
sql += "quotename(" + field.Key + ") as quotename(" + field.Value + ")";
}
sql += " WHERE idrpt=@id";
答案 1 :(得分:1)
是的,所以你有一个SQL布局,你不能改变,这需要你这样做。这是不幸的,但让我们充分利用它。
正如您在评论中所述,您可能需要某些特殊字符支持,因此请特别转义这些特殊字符。
除此之外,您应该将允许的名称减少为字母数字字符和可能的空格。根据您选择的验证机制(例如regex)验证这些,并仅允许这些字符。这可能会让你大部分都免于SQL注入。
这不是最佳选择,但在这种情况下,它似乎是最好的。