-3

我有这个代码:

<?php
$table = $_GET ["table"];
$query = "SELECT 1 FROM $table";
$st = $pdo->prepare($query);
$st->execute();

这不是真正的代码,但它是一个例子。

如果我做:

hacked.php?table=users;DROP TABLE users;

它会起作用,因为它没有正确转义。

但是,如果我想更新这样的信息:

hacked.php?table=users; UPDATE users SET name="abc" WHERE name="def";

它不起作用,因为它被转义了,pdo 会将查询转换为

SELECT 1 FROM users; UPDATE users SET name=\"abc\" WHERE name=\"def\";

显然它失败了。

反正有没有使这个查询有效?

编辑 1

我们团队中有一个人只致力于检查我的代码并破解它。所以我想做好准备,如果这可以以某种方式完成。

编辑 2

我已经读过这个:PDO 准备好的语句是否足以防止 SQL 注入?但它确实没有回答我的问题。然而,它给了我一个通过的方法。@duskwuff 的解决方案与我的解决方案相同。因此,对于管理员来说,如果应该将其删除或标记为重复是可以的。但我坚持认为,这有助于人们了解 pdo prepare 是如何被黑客入侵的。

4

2 回答 2

3

我想你问错问题了。如果您的代码与此非常相似,那么您编写代码的方式就有很大的问题......并且可能与您将需要解决的问题概念化的方式有关,或者您正在从一个非常糟糕的设计开始工作。

如果出于某种原因,您需要在 URL 查询字符串或 http 帖子中传递有关数据库设计的任何信息,并且如果出于某种原因,您认为执行非转义查询是您需要的方法...那么无论你在做什么,你都做错了

如果您确实需要将表格名称传递给网页,那么您至少需要将输入值与某种静态结构进行比较,以查看输入值是否在列表...然后使用列表中的值,或者来自静态的值,而不是来自输入的值。

简单地说,像下面这样原始的东西将是一种优越得多的方法,尽管如果表名、列名或任何数据库内部需要进入浏览器领域,可以说这是一个糟糕的设计。

$table = $_GET ["table"];
IF ($table == "users")
{
   $query = "SELECT 1 FROM users;"
}
ELSEIF ($table == "points")
{
   $query = "SELECT 1 FROM points;"
}  

...

于 2013-09-05T03:35:07.403 回答
3

它不起作用,因为它被转义了,pdo 会将查询转换为

SELECT 1 FROM users; UPDATE users SET name=\"abc\" WHERE name=\"def\";

这是不正确的!PDO 不会对插入查询的文本执行转义,因为它不知道插入了什么文本。您所看到的是 PHP 已弃用的magic_quotes功能在请求变量(如$_GET$_POST)的内容中添加反斜杠的结果。即使启用了此功能,也可以通过使用不带引号的结构来轻松避免此类查询,例如:

SELECT 1 FROM users; UPDATE users SET name = CHAR(97,98,99) WHERE name = CHAR(100,101,102)

CHAR()是一个 MySQL 函数,它从字符代码值列表构造一个字符串。如果您使用的是其他数据库,则可能存在等效函数。)

将未转义的内容直接插入到查询中是不安全的。不要这样做。

于 2013-09-05T03:39:24.900 回答