通过替换单引号来防止SQL注入

时间:2013-09-04 15:11:37

标签: php sql-injection

我已经读过,替换用户输入对于SQL注入是不安全的。 我想知道(可能有一个例子)这样的东西有什么问题(PHP):

function formatsql($testo){
    return str_replace("'", "'", $testo);
}

$username = formatsql($_POST["username"]);
$password = formatsql($_POST["password"]);

$query = "SELECT id FROM utenti WHERE user='$username' AND password='$password'";

1 个答案:

答案 0 :(得分:2)

  

我想知道这样的事情有什么问题(PHP)

这个想法。

很久以前就证明它存在缺陷。

首先,这段代码确实改变了数据。这是抽象思考的好方法,但它会在现实生活中使你的应用程序崩溃。事实上,这是不可接受的行为。但是,您可以转义引号而不是替换它们。

其次,您(就像大多数PHP人员一样)认为替换某些字符会使您的数据安全。虽然不是。每个关心在注射保护领域重新发明轮子的PHP用户总是假设只有字符串被添加到查询中。他们从未明确地意识到它,也没想象SQL查询中存在任何其他部分。虽然这样的替换对于任何其他SQL文字都像鸡一样无害。而且你的功能的名字肯定是我的话语的证据 说,你有这样的代码

$limit = formatsql($_POST["limit"]);
$query = "SELECT id FROM utenti LIMIT $limit";

欢迎任何脚本小子玩你的数据库。

此外,您的推理中还有一个术语“用户输入”,这是二阶注入的确定标志。

更进一步,让我们观察两种应用程序:某种愚蠢的主页脚本和相对较大的Web应用程序。虽然你的代码完全适合前者,但后者的规则会发生变化。有时我们可以拥有代码的这两部分

$username = formatsql($_POST["username"]);
$password = formatsql($_POST["password"]);

$query = "SELECT id FROM utenti WHERE user='$username' AND password='$password'";

彼此戏剧性地分开。在这里,我们可以陷入许多麻烦,例如双重逃逸,错误逃避,完全没有逃脱。

这就是很久以前手动转义被认为是不良做法的原因。

相反,必须使用准备好的陈述,因为保证

  • 完整格式应用而不是愚蠢的“转义”或“替换”
  • 不同的格式应用于不同的数据类型。
  • 格式化应用正确必须在哪里 - 不早或不晚。
  • 正确应用无条件格式,独立于开发人员的意愿或空气。

这就是为什么准备好的陈述已经很久以前认为唯一正确的方法