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


SQL Injection prevention by replacing single-quote

我读到替换用户输入对于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'";

我想知道这个(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'";

彼此显著分离。在这里,我们可能会陷入很多麻烦,比如双重逃避、错误逃避、根本无法逃避。

这就是为什么手动转义在很久以前就被认为是的坏做法。

相反,必须使用准备好的声明,因为它们保证

  • 完成应用的格式设置,而不是愚蠢的"转义"或"替换"
  • 应用于不同数据类型的不同格式
  • 格式设置应用于的适当位置,不早也不晚
  • 无条件地应用适当的格式,独立于开发人员的意愿或空气

这就是为什么准备的声明很久以前就认为是唯一正确的方式的原因。