【问题标题】:Parameterise table name in .NET/SQL?在.NET/SQL 中参数化表名?
【发布时间】:2010-09-27 04:29:36
【问题描述】:

正如主题所暗示的,我希望能够使用 .NET(实际上并不关心哪种语言)和 SQL Server 将表名作为参数传递。

我知道如何为值执行此操作,例如command.Parameters.AddWithValue("whatever", whatever) 在查询中使用@whatever 来表示参数。问题是我希望能够对查询的其他部分(例如列名和表名)执行此操作。

这不是一个理想的情况,但它是我必须使用的,它不太容易发生 SQL 注入,因为只有使用代码的人才能设置这些表名,而不是最终用户。但是很乱。

那么,我要问的可能吗?

编辑:为了清楚说明 SQL 注入,表名仅由源代码传入,具体取决于具体情况。指定这一点的是开发人员。无论如何,开发人员都可以访问数据库层,所以我问的原因不是为了安全,而是为了让代码更干净。

【问题讨论】:

    标签: sql .net sql-server parameters


    【解决方案1】:

    您不能直接参数化表名。您可以通过sp_ExecuteSQL 间接执行此操作,但您也可以在 C# 中构建(参数化)TSQL(连接表名但不连接其他值)并将其作为命令发送。您将获得相同的安全模型(即您需要明确的 SELECT 等,并假设它未签名等)。

    另外 - 请务必将表名列入白名单。

    【讨论】:

      【解决方案2】:

      我不认为我在我见过的任何 SQL 方言中都见过这种能力,但这不是一个专业领域。

      我建议将字符限制为 AZ、az、0-9、'.'、'_' 和 '' - 然后对数据库使用任何适当的括号(例如,我相信 SQL Server 的 [] ) 环绕整个事物。然后直接放到SQL里面就行了。

      不完全清楚你的意思是它不是 SQL 注入风险 - 你的意思是名称将在源代码中并且仅在源代码中?如果是这样,我同意这会让事情变得更好。您甚至可能不需要自动进行包围,如果您相信您的开发人员不是白痴(有意或无意)。

      【讨论】:

      • 是的,源代码并且仅在源代码中。这是为了在我重构这件事时更轻松地构建更新/插入语句。
      【解决方案3】:

      您可以像传递任何其他参数一样将表名作为参数传递。关键是您必须构建一个动态 sql 语句,然后您应该考虑在您的应用程序层或 procs 中构建它是否更容易。

      create procedure myProc
      
      @tableName nvarchar(50)
      
      as
      
      sp_executesql N'select * from ' + @tablename
      

      仅供参考,此代码示例来自内存,请查看 BOL,了解 sp_executesql 的正确语法。

      此外,这很容易受到 SQL 注入的影响,因为您指出这对您来说不是问题,但任何阅读本文的人都应该非常警惕接受来自用户的输入以生成这样的查询。

      【讨论】:

      • 将'从'+@tablename中选择*。然后参数化? (使用 VB.Net 代码,而不是存储过程)。
      • 如果您在 vb.net 中构建查询,则不需要对 @table 进行参数化。您的 vb 代码看起来像 sqlString="select * from " + tableName。然后您将使用命令对象执行 sqlString 。 (将命令类型设置为文本)
      【解决方案4】:

      SQL 查询参数只能代替文字值。您不能将参数用于表名、列名、值列表或其他 SQL 语法。这是所有品牌数据库的标准 SQL 行为。

      使表名动态化的唯一方法是在将字符串准备为语句之前将变量插入到 SQL 查询中。

      顺便说一句,如果您认为这不是 SQL 注入的风险,那您就是在自欺欺人。如果您将表名动态插入到查询中,则需要在表名周围使用 delimited identifiers,就像在从变量中插入的字符串文字周围使用引号一样。

      【讨论】:

        【解决方案5】:

        认为它不容易发生 SQL 注入的想法是错误的。它可能不太容易受到来自前端用户的 SQL 注入的影响,但它仍然很容易受到 SQL 注入的影响。大多数对数据库的攻击来自被攻击的公司内部,而不是来自最终用户。

        员工可能怀恨在心,他们可能不诚实,他们可能心怀不满,或者他们可能只是不够聪明,认为可以绕过安全措施去做他们认为应该做的任何事情对数据库进行处理。

        【讨论】:

        • 我正要说这个,只是投了票。除非参数是硬编码选择,否则这是一个坏主意。
        • 好吧,公司里的人也无权访问。只有调用方法才能指定字段和表名。确实,任何有权访问业务逻辑的人也可以访问数据访问代码,
        【解决方案6】:

        请查看用户 Vimvq1987 的帖子回答: MySqlParameter as TableName

        基本上,您首先会根据模式检查表名,其中表名以参数化方式使用。然后,如果一切正常,表名是合法的。

        转述的基本思想是:

            SELECT table_name
            FROM information_schema.tables
            WHERE table_schema = 'databasename'
            AND table_name = @table;
        
            cmd.Parameters.AddWithValue("@table",TableName);
        

        如果这对表名返回 ok,请继续您的主查询...

        【讨论】:

          【解决方案7】:

          我只是检查一下 select OBJECT_ID(@tablename) 这个想法是为了防止注入你知道它必须是表名这是如果它返回一个数字那么我将运行实际查询,

          【讨论】:

            猜你喜欢
            • 2012-11-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-08-11
            • 1970-01-01
            • 2021-09-21
            • 1970-01-01
            • 2011-10-23
            相关资源
            最近更新 更多