虽然参数是防止Sql注入的最佳方法,但有时我们无法在构建动态查询时使用它。例如,表/列/索引名称不能作为参数传入,而只能传递纯文本。
好像是
SqlCommandBuilder.QuoteIdentifier
是我能找到的唯一选择。调用这种方法足以保护自己吗?
MSDN DOC:
在正确的目录案例中给出一个不带引号的标识符,返回 正确引用该标识符的形式。这包括正确 转义标识符中的任何嵌入式引号。
例如是
"Select * FROM " + SqlCommandBuilder.QuoteIdentifier("CustomTable" + userInputText);
安全吗?
编辑:查询只是一个例子。我有兴趣了解是否有可能进行Sql注入。
答案 0 :(得分:2)
它不会保护你免受攻击者去你不想要的桌子。
例如SQL系统表......
答案 1 :(得分:1)
这可能不安全。
为了防止SqlCommandBuilder.QuoteIdentifier方法出现任何可能的安全问题,您需要做的就是从数据库中获取可用表名等的列表,并根据它们验证用户输入。
编辑添加:我有理由怀疑QuoteIdentifier
是否完全安全:SqlCommandBuilder.QuoteIdentifier Method的文档说明(如您之前所引用的):
在正确的目录案例中给出一个不带引号的标识符,返回该标识符的正确引用形式。这包括正确转义标识符中的任何嵌入式引号。
在文档中没有任何地方说明如果在错误的目录案例中给出了一个不带引号的标识符(无论“目录案例”是什么),会发生什么。或者如果标识符长于maximum allowed会发生什么。当然,不能依赖未定义的行为。
答案 2 :(得分:0)
对我来说似乎很安全。此外,这可能是一个很好的参考:
Sanitize table/column name in Dynamic SQL in .NET? (Prevent SQL injection attacks)
答案 3 :(得分:0)
使用表名字段中的用户输入永远不会安全,无论您尝试检查多少(除非您将条目限制为一组有限的名称或做其他类型的巫术)。
即使删除引号,用户也可以输入:TableName; DROP DATABASE db;
或(SELECT * FROM <sensible table)
。
可能的解决方案是:
ComboBox
或同等用户无法修改选项String[]
的输入是否包含所有允许的表名(它们应与其中一个条目相同)如果用户输入的表名只是一个示例,但您要将输入用作WHERE
的{{1}}子句的一部分,那么您应该检查{ {3}}
引自网站:
来自Bobby Tables wiki页面C# Online
SELECT
或更简单:
SqlCommand userInfoQuery = new SqlCommand(
"SELECT id, name, email FROM users WHERE id = @UserName",
someSqlConnection);
SqlParameter userNameParam = userInfoQuery.Parameters.Add("@UserName",
SqlDbType.VarChar, 25 /* max length of field */ );
// userName is some string valued user input variable
userNameParam.Value = userName;
答案 4 :(得分:0)
你考虑过使用OData吗?您可以传入文本,选择表格,索引等。但是使用OData,您可以选择要以这种方式发布的表,并且它不会被注入攻击,因为您必须明确允许更新和插入操作。
http://www.odata.org/documentation/odata-version-2-0/uri-conventions/ https://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api