使用 OleDb 参数的目的是啥? [复制]

Posted

技术标签:

【中文标题】使用 OleDb 参数的目的是啥? [复制]【英文标题】:What is purpose of using OleDb Parameters? [duplicate]使用 OleDb 参数的目的是什么? [复制] 【发布时间】:2021-12-31 21:06:30 【问题描述】:

我有使用 OLEDB 将数据输入数据库的代码。假设它看起来像这样

var commandText = $"INSERT into tableName
                (columnName1, columnName2)
                VALUES (value1, value2);"
var command = new OleDbCommand(commandText, connection);
command.ExecuteNonQuery();

建议使用OLEDB参数,类似这样

var commandText = $"INSERT into tableName
                ([columnName1], [columnName2])
                VALUES (?, ?);"
var command = new OleDbCommand(commandText, connection);
command.Parameters.Add(new OleDbParameter(columnName1, value1));
command.Parameters.Add(new OleDbParameter(columnName2, value2));
command.ExecuteNonQuery();

在这里使用参数有什么好处?

如果之前验证过这些值,真的会提高安全性吗?

【问题讨论】:

Does it really improve security if the values are validated before? - 。因为总会有一个比你的验证更聪明的攻击者(白名单除外)。您还应该真正尝试重构您的软件,这样您就不必以这种方式注入表/列名。参数化语句还可能有助于提高性能并防止无数的语法错误。 (总是期望你的用户是愚蠢的,而你的攻击者是聪明的) 简而言之,是的。连接到 SQL Server,将value 设置为1, 2); DROP DATABASE MyDb; --,你就遇到了经典的 SQL 注入攻击,有很多方法可以重写它并逃避检测。更重要的是,像NULL 这样的值、带引号的字符串和日期/时间文字在插入值时都需要特别注意。值被“验证”的想法很好,但参数构成了注入攻击的绝对障碍,而验证则没有。 假设您有以下查询:string query = "SELECT Id FROM Users WHERE Name = '" + userName + "' AND password = '" + password + "'";,然后有人输入用户名值' OR Name = 'SysAdmin' ; -- comment。被执行的查询将被组合成这样:"SELECT Id FROM Users WHERE Name = '' OR Name = 'SysAdmin' ; -- comment' AND password = 'somevalue';。就这样,用户以管理员身份登录!或者更糟糕的是,他们的“用户名”是' ; DROP TABLE User; -- comment,而您刚刚丢失了用户表。已验证,当然。确信自己没有错过什么? some fundamental infos about SQL Injection attacks 这不仅仅是安全性。参数是强类型的二进制值。您避免了代码中的类型转换和本地化问题(什么日期格式?什么小数分隔符?)节省空间。使用参数允许重用执行计划,从而显着提高性能,尤其是对于简单频繁执行的查询 【参考方案1】:

使用此代码,再多的参数也无济于事。

连接表名和列名的事实使您的查询容易受到 SQL 注入攻击,这是使用参数的主要(但不仅是)原因。

SQL 注入的工作方式是将发送到数据库的部分字符串替换为 sql 代码。参数可以防止这种情况发生,因为数据库将它们视为数据的占位符,这意味着它不会运行任何通过它们传递的 sql 代码。 但是,由于您的表名和列名也是 c# 变量,因此可以将它们替换为数据库将尝试运行的 SQL 代码。

假设如下代码:

var tableName = "table (Col1) VALUES (null);DROP TABLE table;--";

// declare and populate columnName1, columnName2 with whatever values you want here, even just nulls

var commandText = $"INSERT into tableName
                ([columnName1], [columnName2])
                VALUES (?, ?);"
// run SQL command here

这将在table 中插入一条记录,然后从数据库中删除该表。

欲了解更多信息,请阅读我题为Back to basics: SQL Injection的博文

【讨论】:

【参考方案2】:

事实上,是的。我们都会犯错,而参数对象所增加的额外安全性就像第二双眼睛。 此外,如果您始终使用参数对象,则在后续引入错误的风险会更小。

【讨论】:

不是这样的。再多的手动检查和转义也无法阻止使用参数消除的 SQL 注入问题、类型转换或本地化错误。参数也通过使用缓存的执行计划来提高性能,而使用动态 SQL 根本无法做到这一点。当您传递 DateTime 参数值时,您传递的是明确的二进制 DateTime 值,而不是本地化字符串。 @PanagiotisKanavos 谢谢。你说的比我好得多,但重点仍然是正确的。恕我直言,永远不要使用没有参数对象的 SQL。

以上是关于使用 OleDb 参数的目的是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

将方法参数声明为 final 的目的是啥? [复制]

**kwargs 的目的和用途是啥? [复制]

argc 和 argv 的目的是啥? [复制]

使用 JDBC 参数化 IN 子句的最佳方法是啥? [复制]

OAuth 2身份验证中grant_type参数的目的是啥

JAVA中REENTRANT LOCK中公平参数的目的是啥?