2

我熟悉准备好的语句,并且我知道它们是防止 MySQL 注入的最佳实践。但我想知道这个 PHP/MySQL 语句如何可能面临注入攻击的风险:

$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".$_POST['name']."';");

在我看来,用户的输入将包含在单引号内。您可以在一条语句中执行多个查询mysqli_query吗?

此外,使上述安全就像这样简单......

$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".mysqli_real_escape_string($_POST['name'])."';");
4

5 回答 5

3

在我看来,用户的输入将包含在单引号内

攻击者所要做的就是在名称 POST data 中加上一个单引号,这样就不会再有了。

name=' OR 1=1

另外,使上述安全变得像这样简单吗

看起来不错……但它伤害了我的眼睛。使用准备好的语句。它们比通过将字符串连接在一起构建的 SQL 更容易阅读。

于 2013-01-14T17:07:06.910 回答
3

在我看来,用户的输入将包含在单引号内

除非您在张贴中包含单引号,否则name它将允许您跳出引号。例如,将名称发布为:

' or 1 or '

WHERE 子句变为:

WHERE id = '' or 1 or '';

由于该部分,这将匹配并检索表中的所有行or 1。正如你所看到的,它打破了引号以注入一些 SQL,然后它返回到引号中以使查询有效。

您可以在一条语句中执行多个查询mysqli_query吗?

不,但如果它是用mysqli_multi_querythen yes 执行的,你可以在最后添加多个查询。

使上述安全变得一样容易mysqli_real_escape_string吗?

通常是的,但准备好的声明会更好。使用转义,WHERE子句将变为(使用我上面的示例):

WHERE id = '\' or 1 or \'';

这不再容易受到攻击,因为引号不能被打破,并且只会在name字面上匹配时才匹配行,' or 1 or '这显然不太可能。

于 2013-01-14T17:22:29.963 回答
1

基本解释:

如果您只是按照第一个示例插入查询,则如果变量包含单引号字符$_POST['name'],则生成的 SQL 字符串将无效。name

这将立即惹恼任何名为 O'Brien 或类似名称的人。

但这可能会被黑客利用,黑客可以修改他的“名称”,在单引号后包含有效的 SQL 代码。这可以是任何有效的 SQL,允许黑客对您的数据库执行任何操作或从中查询任何内容。他能做什么将取决于您代码中的其他因素,但足以说明即使在最好的情况下,他也可以做​​一些非常具有破坏性的事情。

回答你的第二个问题:是的。转义使用mysqli_real_escape_string()将缓解这个问题。

但是,为了更进一步,您可能还想使用Prepared Queries 进行调查,这是mysqli扩展的一项功能。这可以使您的代码更整洁,因为它避免mysqli_real_escape_string()了在所有地方都使用那个讨厌的长函数名。它还具有其他好处,例如改进的查询缓存。

希望这有助于回答这个问题。

于 2013-01-14T17:10:15.200 回答
0

如果我传递了以下值$_POST['name']怎么办?

'; DELETE FROM users WHERE name <> '

我将关闭第一个单引号,然后引入破坏性查询,该查询最后只有一个打开的引号,它将被原始查询中的单引号关闭。

你的第二个查询很好。虽然你真的应该考虑使用准备好的语句(由 mysqli 支持)

于 2013-01-14T17:08:11.450 回答
0

如果您正在使用mysqli,则应始终使用 SQL 占位符方法来执行此操作。转义函数是困难的方法。

$stmt = $db->prepare("SELECT name FROM users WHERE id = ?");
$stmt->bind_param('i', $_POST['name']);
$stmt->execute();

如果你不了解这里的风险,你真的需要阅读一般的SQL 注入攻击,并阅读自动化黑客工具可以对那些不够谨慎的人做什么。

于 2013-01-14T17:09:00.693 回答