表名sql注入
本文关键字:注入 sql 表名 | 更新日期: 2023-09-27 18:21:11
我正在使用C#。我需要编写一个选择内联查询。
表名应取自config。我无法编写存储过程。
SqlCommand myCommand= new SqlCommand();
myCommand.CommandText = "Select * from " + tableName;
myCommand.CommandType = CommandType.Text;
myCommand.Connection = connString;
如何避免sql注入?
只需创建一个带有真实参数的查询,并检查表名是否存在,比如:
SELECT COUNT(*) FROM SYS.TABLES WHERE NAME = @pYOURTABLENAME
如果返回1,那么您就知道该表存在,因此可以在问题中显示的SELECT
中使用它。。。
然而,我强烈建议您尝试任何方法来消除对任何易于SQL注入的代码的需求
我会确保表名只包含以下字符:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]. -_0123456789
例如,
Regex regex = new Regex(@"^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[']. -_0123456789]{1,128}$");
if (!regex.IsMatch(tableName)) throw new ApplicationException("Invalid table name");
要进行更全面的工作,包括非英语语言,请参阅以下关于有效表名称的参考:http://msdn.microsoft.com/en-us/library/ms175874.aspx
您需要验证tableName
是否合适。在进行了一些健全性检查(确保它没有空格或其他不允许使用的表名字符等)后,我将首先在数据库中查询所有表的名称,并通过编程验证它是否是这些表名之一。然后继续运行您显示的查询。
我会考虑将SQL迁移到存储过程中,并回顾Erland Sommarskog的这篇文章,因为它对在存储过程中使用动态SQL有一些很好的想法。我当然会研究一下。它讨论了许多关于SQL注入的问题,以及动态SQL的可能替代方案。
他还有另一篇关于如何在存储过程中使用数组的伟大文章。我知道你没有要求这样做,但我经常提到这两篇文章,因为我认为它们很有见地,为你编写程序提供了一些有用的想法。
除了上面链接的一些建议之外,如果我使用动态SQL,我仍然可以使用一些基本的参数净化机制。这方面的一个例子如下;
IF LEN(@TableName) < 5 OR LEN(@TableDisplayName) < 5
BEGIN
RAISERROR('Please ensure table name and display name are at least 5 characters long', 16, 1)
END
IF NOT (@TableName not like '%[^A-Z]%')
BEGIN
RAISERROR('The TableName can only contain letters', 16, 1)
END
IF NOT (@TableDisplayName not like '%[^0-9A-Z ]%')
BEGIN
RAISERROR('The TableDisplayName can only contain letters, numbers or spaces', 16, 1)
END
再加上在动态sql中使用参数,然后使用sp_executesql执行,这无疑有助于将sql注入攻击的可能性降至最低。