我目前正在编写一个需要针对 SQL 注入的可靠安全性的应用程序。我的问题是这个。将您的输入参数与您的准备语句分开以防止 SQL 注入是绝对要求,还是您可以简单地准备任何语句以确保它没有 SQL 注入?
换句话说,我可以使用 mysqli_prepare 作为一个简单的检查来确保在我之前构建的语句中没有注入 SQL 吗?或者是绑定参数的整个过程,并使用后续返回的语句结构来处理服务器返回的信息?
我目前正在编写一个需要针对 SQL 注入的可靠安全性的应用程序。我的问题是这个。将您的输入参数与您的准备语句分开以防止 SQL 注入是绝对要求,还是您可以简单地准备任何语句以确保它没有 SQL 注入?
换句话说,我可以使用 mysqli_prepare 作为一个简单的检查来确保在我之前构建的语句中没有注入 SQL 吗?或者是绑定参数的整个过程,并使用后续返回的语句结构来处理服务器返回的信息?
准备语句是由 SQL 引擎完成的。您提前向服务器发送查询,例如:
Prepare : SELECT id, x FROM y WHERE id = ?
然后,?
绑定到数据;您的抽象层甚至可以强类型化(PDO 可以做到这一点,因为您可以让它在格式化和输入数据之前进行显式转换)
在准备中,数据和语句(查询)是完全分开的。查询正在服务器上等待,准备好被调用,如果存在数据字段,它将等待输入。
这有一个主要好处,因为您可以完全分离逻辑和数据,还因为查询存储在服务器上,随时可以调用。这意味着,如果您必须为大量插入数据调用数千次查询,那么为性能做好准备几乎总是更好。
简单地准备一个已经包含用户输入的语句不会使其安全。在添加用户输入之前,您必须分离数据和逻辑。
将输入参数与准备语句分开以防止 SQL 注入是绝对要求吗
或多或少。
您可以使用其他技术来保护自己,有时您必须使用它们,但是?
在准备好的语句中使用 10 次中有 9 次是最简单、最清晰且通常最好的解决方案。
或者您可以简单地准备任何语句以确保它没有 SQL 注入?
不会。如果您在准备语句之前将用户数据混合在一起创建了有害的 SQL,那么准备语句根本不会为您提供任何保护。
保护来自绑定参数,而不是来自准备好的语句。这两件事通常是齐头并进的,因此有时会将各自的好处错误地归因于错误的功能。
如果您的意思是:
$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; --'
然后没有人能够分辨出该语句的哪个部分是由用户插入的,以及它的意图是什么。事后准备这个查询是没有意义的。
每当将参数发送到服务器时,使用准备好的语句是一种很好的做法。没有理由不。这是防止 SQL 注入的绝对最低限度。
当然,如果不发送参数,SQL 注入就不是问题。