11

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

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

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

那么,我要问的可能吗?

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

4

7 回答 7

7

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

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

于 2008-12-16T17:39:13.293 回答
4

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

create procedure myProc

@tableName nvarchar(50)

as

sp_executesql N'select * from ' + @tablename

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

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

于 2008-12-16T17:35:54.517 回答
4

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

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

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

于 2008-12-16T17:37:09.210 回答
4

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

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

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

于 2008-12-16T17:38:02.720 回答
2

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

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

于 2008-12-16T18:14:43.410 回答
0

请参阅用户 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,请继续您的主查询...

于 2013-07-11T14:40:56.420 回答
0

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

于 2015-02-27T21:57:26.683 回答