SQL注入,最简单的解决方案

SQL注入,最简单的解决方案,sql,sql-server,oracle,tsql,plsql,Sql,Sql Server,Oracle,Tsql,Plsql,如果我简单地用双引号替换所有传入的单引号,我不确定有人会如何破坏我的SQL。有人能告诉我Oracle和SQL Server的例子吗?谢谢 string sql1 = "select * from users where user_id = '" + "O'Reily".Replace("'", "''").Replace("\", "") + "'"; ==>“从用户id为'O''Reily'的用户中选择*” ==>“从用户id为“O”的用户中选择*” 更新:斜杠“\”在应用程序中是一个限制字

如果我简单地用双引号替换所有传入的单引号,我不确定有人会如何破坏我的SQL。有人能告诉我Oracle和SQL Server的例子吗?谢谢

string sql1 = "select * from users where user_id = '" + "O'Reily".Replace("'", "''").Replace("\", "") + "'";
==>“从用户id为'O''Reily'的用户中选择*”

==>“从用户id为“O”的用户中选择*”


更新:斜杠“\”在应用程序中是一个限制字符,在查询中使用前将被去掉。可以很容易地将双破折号添加到此限制字符列表中。

您建议的解决方案容易受到包含
\'
字符串的影响,该字符串将结束您引用的部分并允许t他还发出了其他命令

您希望在任何可能的地方使用SQL准备的语句,这些语句应该无处不在。基本上,您使用数据的特定占位符编写SQL,然后通过一个单独的非解释通道将数据传递给SQL server

几个链接:


对变量进行参数化。说真的。所有现代环境都有这样做的工具,您不必担心转义序列,例如“\”会随着您的方案(在Oracle中)变为“\”,它会变成转义引号和常规(终止)引号

有很多其他的技巧来实现这一点,我没有列举,因为它们没有帮助

再一次:参数化你的变量。说真的。如果你不学会如何使用参数化,你将成为另一个被黑客攻击的统计数据

编辑:阅读Paul答案中的链接,这里是另一个:

不管你认为你的字符串有多聪明,你都做得不对,尤其是当你必须处理多个后端的时候


用字符串编写查询是我将解雇员工的为数不多的事情之一……这样的程序员给公司带来的风险比他们带来的任何其他东西都要大(特别是在我们明确表示我们不会在第一天接受这样的代码,并提供一个实体框架使这些事情变得不必要之后).

为了防止SQL注入,您真正应该做的是使用绑定的位置参数或命名参数,而不是将SQL构造为内联用户输入的字符串。这取决于应用程序访问数据库的方式。例如,在使用JDBC的Java中,它是什么样子的:

坏的:

好:

我从这里借用了一个例子:

攻击者利用应用程序截断输入时会用到一些技巧:


单引号与其说是问题,不如说是“-”和“;"。尽可能限制用户文本输入。强制性的小Bobby表:Bobby可以使用此解决方案。单引号将转义为双引号,删除操作将永远不会执行。“--”和“;”在字符串文字中毫无意义,应该被允许。限制像这样的任意内容是迷信:正确地转义,您就不必担心它们;如果无法正确地转义,它们就不会救您。这真的会阻止我键入updateSales.setString(2,“删除您的_数据;”--rexem:是的。例如,Oracle将通过解析阶段来检查SQL的语法。在这一点上,它不会查看绑定变量的内容。如果不成功解析SQL,则无法执行SQL。在“好”示例中,参数定义为绑定变量,决不会作为SQL语句的一部分进行解析,并且不能执行er可以被执行。作为一种“副作用”,语句可以对不同的绑定变量值进行重用,从而减少对数据库的解析和加载。如果支持+1,则使用绑定变量。我认为在php中不支持。但是java、c#、c/c++……大多数语言都支持。因为sql是解析(或解释)的从值中分离出来,这是防止sql注入的唯一安全措施。感谢这是一个很好的链接,但它依赖于将字符串数据修剪为固定宽度,然后剥离已实现的修复。此外,asp代码中输入的长度与输出到数据库的长度不匹配。+1完全同意这一点在哪些情况下你会变得那么聪明(错误)创建解决方案时的感受。我们有一家安全渗透公司试图入侵我们的网站。因为我们使用参数,它们在字符串操作方面没有取得任何进展…但我在日志中看到了许多奇怪的构造,我后来尝试过。令人惊讶的是,在这个主题上有如此多的变体。谢谢,我知道这是正确的方法。我一直认为,在某种程度上,参数化数据无论如何都是在进行某种正则表达式/字符串操作。参数化不进行字符串操作,这是好处之一。相反,参数与命令字符串一起发送,就像语言w中函数调用的参数一样应该是。当在服务器端解析参数时,命令字符串已经应用了所有转义,并且参数具有实际类型。这意味着作为参数的“O'Dell”字面上是“O'Dell”,而不是转义的“O'Dell”。这还意味着500是整数参数中的整数,而不是“500”。整数参数将拒绝“ABCD”就像语言中的函数一样。
string sql2 = "select * from users where user_id = '" + "O'''Reily".Replace("'", "''").Replace("\", "") + "'";
String updateString = "UPDATE COFFEES SET SALES = 75 " + 
                      "WHERE COF_NAME LIKE 'Colombian'";
stmt.executeUpdate(updateString);
PreparedStatement updateSales = con.prepareStatement(
        "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75); 
updateSales.setString(2, "Colombian"); 
updateSales.executeUpdate():