在模式/表名称中使用'['和']'字符时如何避免SQL注入?

时间:2010-10-23 13:07:59

标签: c# security tsql sql-injection

我有几个上下文,其中表名或模式不是硬编码的,而是由管理员配置,或者更糟糕的是,从用户输入生成。

由于案例很简单(模式和表名用普通英语,没有数字或符号),因此只能禁止A-Za-z范围之外的任何字符来避免SQL注入。但是当应用程序必须处理任何Unicode字符时,这种方法很糟糕,因为它可以是模式或表的名称的一部分。

现在,如果SQL查询使用'['']'来包含模式,表和列的名称,是否足以禁止名称中的']'字符以避免SQL注入?

示例:

A'B是表格的有效名称。所以:

string tableNameFromUserInput = "A'B"; // Let's imagine it is a user input.
using (SqlCommand getEverything = new SqlCommand(
    string.Format("select * from [dbo].[{0}]", tableNameFromUserInput),
    sqlConnection)
{
    // Do stuff.
}

完全有效,没有理由阻止单引号字符。

以下代码中是否存在SQL注入风险?

string tableName = UserInput.GetUnsafeInputFromUser();

// Search for ']' character only.
if (tableName.IndexOf(']') != -1)
{
    throw new HackerDetectedException();
}
else
{
    using (SqlCommand getEverything = new SqlCommand(
        string.Format("select * from [dbo].[{0}]", tableNameFromUserInput),
        sqlConnection)
    {
        // Do stuff.
    }
}

修改

经过一些搜索,我发现的是Microsoft SQL中Delimited identifiers上的一篇文章。根据它:

  

标识符的主体可以包含当前代码页中的任何字符组合,但分隔字符本身除外。

顺便说一句,分隔标识符限制为128个字符。

所以要让它发挥作用:

  • 必须禁止']'字符(或者更好,由']]'替换;请参阅下面的Mark Byers答案。)
  • 长度必须限制为128个字符(上面的示例代码中未完成),
  • 可能必须检查代码页才能获得正确的表格。

4 个答案:

答案 0 :(得分:3)

我认为那样安全。反斜杠等字符被视为文字字符,因此它们应安全地包含在表名中。我可以立即认为是一个问题的唯一字符是],你已经不允许这样做。顺便说一下,要将]包含在表名中,需要将其写为]],因此不必完全拒绝它,而是可以tableName.Replace("]", "]]")

但为了安全起见,您应该按照建议使用白名单。为了在允许表名中的unicode字符的同时执行此操作,您可能需要考虑使用正则表达式@"^\w+$"来验证表名,因为它也接受unicode字符。

答案 1 :(得分:2)

如果它只是选择sql,即你不打算保存任何更改,你可以在try块中的事务中运行sql命令并在finally块中回滚。

这样,您可以在代码级别确保不会从您的代码运行任何其他ddl,dml。只有选择的声明才会执行。

当您获取数据但未更新数据时,此特定的startegey会起作用。

   try
        {
            //Run command in transaction.
        }
        catch (Exception ex)
        {
            // rollback transaction
        }

        finally
        {
            // rollback transaction
        }

并且已经针对Sybase数据库进行了测试

答案 2 :(得分:2)

不确定您的内联SQL有多复杂,但为什么不通过QUOTENAME()从用户传递架构/表字符串来转义无效字符?

答案 3 :(得分:0)

我认为以下内容可能会破坏您的数据库,可能是OWASP中的以下内容:
'and 1 in (select min(name ) from master.dbo.sysdatabases where name >'.' ) --'

对于任何想要OWASP资源的人:
OWASP