1

我目前正在编写一个需要针对 SQL 注入的可靠安全性的应用程序。我的问题是这个。将您的输入参数与您的准备语句分开以防止 SQL 注入是绝对要求,还是您可以简单地准备任何语句以确保它没有 SQL 注入?

换句话说,我可以使用 mysqli_prepare 作为一个简单的检查来确保在我之前构建的语句中没有注入 SQL 吗?或者是绑定参数的整个过程,并使用后续返回的语句结构来处理服务器返回的信息?

4

4 回答 4

2

准备语句是由 SQL 引擎完成的。您提前向服务器发送查询,例如:

Prepare : SELECT id, x FROM y WHERE id = ?

然后,?绑定到数据;您的抽象层甚至可以强类型化(PDO 可以做到这一点,因为您可以让它在格式化和输入数据之前进行显式转换)

在准备中,数据和语句(查询)是完全分开的。查询正在服务器上等待,准备好被调用,如果存在数据字段,它将等待输入。

这有一个主要好处,因为您可以完全分离逻辑和数据,还因为查询存储在服务器上,随时可以调用。这意味着,如果您必须为大量插入数据调用数千次查询,那么为性能做好准备几乎总是更好。

简单地准备一个已经包含用户输入的语句不会使其安全。在添加用户输入之前,您必须分离数据和逻辑。

于 2013-06-03T14:42:21.253 回答
2

将输入参数与准备语句分开以防止 SQL 注入是绝对要求吗

或多或少。

您可以使用其他技术来保护自己,有时您必须使用它们,但是?在准备好的语句中使用 10 次中有 9 次是最简单、最清晰且通常最好的解决方案。

或者您可以简单地准备任何语句以确保它没有 SQL 注入?

不会。如果您在准备语句之前将用户数据混合在一起创建了有害的 SQL,那么准备语句根本不会为您提供任何保护。

保护来自绑定参数,而不是来自准备好的语句。这两件事通常是齐头并进的,因此有时会将各自的好处错误地归因于错误的功能。

于 2013-06-03T14:43:02.537 回答
2

如果您的意思是:

$sql = "SELECT foo FROM bar WHERE baz = '$var'";
$query = $db->prepare($sql);
// Wee, we are safe!

然后:没有。

假设$var包含这个:

Robert'; DROP TABLE users; --

的值$sql将是:

SELECT foo FROM bar WHERE baz = 'Robert'; DROP TABLE users; --'

然后没有人能够分辨出该语句的哪个部分是由用户插入的,以及它的意图是什么。事后准备这个查询是没有意义的。

于 2013-06-03T14:43:31.287 回答
0

每当将参数发送到服务器时,使用准备好的语句是一种很好的做法。没有理由不。这是防止 SQL 注入的绝对最低限度。

当然,如果不发送参数,SQL 注入就不是问题。

于 2013-06-03T14:43:33.477 回答