【发布时间】: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,而您刚刚丢失了用户表。已验证,当然。确信自己没有错过什么? -
这不仅仅是安全性。参数是强类型的二进制值。您避免了代码中的类型转换和本地化问题(什么日期格式?什么小数分隔符?)和节省空间。使用参数允许重用执行计划,从而显着提高性能,尤其是对于简单频繁执行的查询