gpt4 book ai didi

c# - 如何参数化 SQL 表而不会受到 SQL 注入(inject)的影响

转载 作者:行者123 更新时间:2023-12-05 08:46:17 25 4
gpt4 key购买 nike

我正在编写一个 C# 类库,其中一个功能是能够创建与任何现有表的架构匹配的空数据表。

例如,这个:

private DataTable RetrieveEmptyDataTable(string tableName)
{
var table = new DataTable() { TableName = tableName };

using var command = new SqlCommand($"SELECT TOP 0 * FROM {tableName}", _connection);
using SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(table);

return table;
}

上面的代码可以运行,但是它有一个明显的安全漏洞:SQL 注入(inject)。

我的第一直觉是像这样参数化查询:

    using var command = new SqlCommand("SELECT TOP 0 * FROM @tableName", _connection);
command.Parameters.AddWithValue("@tableName", tableName);

但这会导致以下异常:

Must declare the table variable "@tableName"

在 Stack Overflow 上快速搜索后,我找到了 this question ,建议使用我的第一种方法(具有 sqli 漏洞的方法)。那根本没有帮助,所以我继续搜索并找到了 this question ,这表示唯一安全的解决方案是对可能的表进行硬编码。同样,这不适用于我的类库,它需要为任意表名工作。

我的问题是:如何参数化表名而不会受到 SQL 注入(inject)的影响?

最佳答案

任意表名仍然必须存在,因此您可以先检查它是否存在:

IF EXISTS (SELECT 1 FROM sys.objects WHERE name = @TableName)
BEGIN
... do your thing ...
END

此外,如果您希望允许用户从中选择的表列表是已知的和有限的,或者匹配特定的命名约定(如 dbo.Sales% ),或者属于特定的模式(如 Reporting ) ,您可以添加额外的谓词来检查这些谓词。

这需要您将表名作为适当的参数传递,而不是连接或标记替换。 (还有 please don't use AddWithValue() for anything,永远。)

一旦检查对象真实有效,您仍然需要动态构建 SQL 查询,因为您仍然无法参数化表名。你还是应该申请QUOTENAME() , 不过,正如我在这些帖子中解释的那样:

所以最终的代码应该是这样的:

CREATE PROCEDURE dbo.SelectFromAnywhere
@TableName sysname
AS
BEGIN
IF EXISTS (SELECT 1 FROM sys.objects
WHERE name = @TableName)
BEGIN
DECLARE @sql nvarchar(max) = N'SELECT *
FROM ' + QUOTENAME(@TableName) + N';';
EXEC sys.sp_executesql @sql;
END
ELSE
BEGIN
PRINT 'Nice try, robot.';
END
END
GO

如果您还希望它在某个定义的列表中,您可以添加

AND @TableName IN (N't1', N't2', …)

LIKE <some pattern>或加入sys.schemas或者你有什么。

如果没有人有权修改程序以更改支票,则没有任何值可以传递给 @TableName这将允许你做任何恶意的事情,除了可能从另一个你没想到的表中选择,因为有太多访问权限的人能够在调用代码之前创建。替换像 -- 这样的字符或 ;不会让这更安全。

关于c# - 如何参数化 SQL 表而不会受到 SQL 注入(inject)的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70013463/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com