通过 php 中的类型提示(使用 >7.0 的版本)函数参数是否使代码 sql 注入安全?
Does by type hinting in php (using versions >7.0) the function parameters make the code sql-injection safe?
我有以下代码(继承自之前的开发):
declare(strict_types=1);
function updateWithCurrentTime(PDO $connection, int $id): void{
$date = date('m/d/Y h:i:s a', time());
$query= "INSERT INTO timetable (id,time) VALUES (${id},${date})";
$connection->query($query);
}
$connection = new PDO('sqlite::memory:');
$connection->query("CREATE TABLE timetable (id INT , date TEXT)");
updateWithCurrentTime($connection,1);
如您所见,它没有按照建议使用准备好的语句,而是直接将参数传递到查询中。但是正如您还可以看到函数 updateWithCurrentTime
中的参数是类型提示的。
所以我想知道通过类型提示函数的输入参数是否可以确保 SQL 注入安全?即使没有使用准备好的语句。
请记住,我假设不会提供任何字符串类型的输入参数,在字符串类型的输入参数中使用准备好的语句是一种方法。
技术上是的。该函数要么优雅地将参数转换为整数,要么抛出 TypeError
异常。这会起作用。
Depending on your strict_types declaration.
实际上 - 反响不佳。
这不是好的做法(您提到了准备好的语句 - 它们是正确的解决方案)。更糟糕的是,您可能无法访问服务器配置,并且您不知道是否启用了严格模式。
严格来说,您显示的查询是安全的,因为您可以保证 $id
只是一个整数值,并且它不会向 SQL 查询中引入会导致任何恶作剧的字符.
但是类型提示解决方案不适用于 string
类型提示。即使你type-hint你的函数参数必须是一个字符串,
function updateWithCurrentTime(PDO $connection, int $id, string $value): void{
$query= "INSERT INTO timetable (id,value) VALUES (${id}, '${value}')"; // UNSAFE
您想知道,$value
是否包含任何引号字符?它是否包含任何其他会引起恶作剧的东西?您无法仅通过使用类型提示来阻止它成为 SQL 注入漏洞。
因此类型提示在使用 int
类型时可能有效,但在 string
类型时无效。其他类型呢?嗯,必须调查...
现在你打开了一堆蠕虫。您必须调查所有类型,并尝试提出完整的指导方针,说明哪些可以安全地插入到 SQL 中,哪些不能。您必须使这些指南足够清晰,以便您的软件开发团队的每个成员都可以遵循它们,并可以在代码审查期间使用它们。
即使您确实完美地编写了代码并针对每种类型使用了适当的 SQL 注入防御方法,但以后阅读代码的其他人也会感到困惑。 "Why aren't variables combined with SQL queries in the same way in different functions?" 他们会想知道。找出原因会占用他们的时间和注意力,使他们无法完成分配给他们的任何代码维护任务。请记住,在您开发此代码后,它将存在多年,并且其他软件开发人员需要维护它。使代码易于理解是值得的。
或者,您可以只使用参数。
SQL 查询参数适用于所有类型,您不必依赖 type-hinting。它们简单、有效,而且您可以始终如一地使用它们。
请停止寻找避免使用查询参数的方法。
打个比方:假设你是电工而不是软件开发人员。您听说电线应该绝缘以避免 short-circuits 的可能性。但出于某种原因,您不喜欢处理绝缘电线。
"I'll just put a shim in between the wires to keep them separated." 但你用作垫片的项目必须是 non-conductive 和 non-flammable.
什么样的垫片可以安全使用?伍德……不。金属……不。塑料……取决于塑料的类型。陶瓷...我不知道,得查一下什么的...
其他电工都会用奇怪的眼光看你。
"Just use insulated wires, are you trying to burn down this building?"
我有以下代码(继承自之前的开发):
declare(strict_types=1);
function updateWithCurrentTime(PDO $connection, int $id): void{
$date = date('m/d/Y h:i:s a', time());
$query= "INSERT INTO timetable (id,time) VALUES (${id},${date})";
$connection->query($query);
}
$connection = new PDO('sqlite::memory:');
$connection->query("CREATE TABLE timetable (id INT , date TEXT)");
updateWithCurrentTime($connection,1);
如您所见,它没有按照建议使用准备好的语句,而是直接将参数传递到查询中。但是正如您还可以看到函数 updateWithCurrentTime
中的参数是类型提示的。
所以我想知道通过类型提示函数的输入参数是否可以确保 SQL 注入安全?即使没有使用准备好的语句。
请记住,我假设不会提供任何字符串类型的输入参数,在字符串类型的输入参数中使用准备好的语句是一种方法。
技术上是的。该函数要么优雅地将参数转换为整数,要么抛出 TypeError
异常。这会起作用。
Depending on your strict_types declaration.
实际上 - 反响不佳。
这不是好的做法(您提到了准备好的语句 - 它们是正确的解决方案)。更糟糕的是,您可能无法访问服务器配置,并且您不知道是否启用了严格模式。
严格来说,您显示的查询是安全的,因为您可以保证 $id
只是一个整数值,并且它不会向 SQL 查询中引入会导致任何恶作剧的字符.
但是类型提示解决方案不适用于 string
类型提示。即使你type-hint你的函数参数必须是一个字符串,
function updateWithCurrentTime(PDO $connection, int $id, string $value): void{
$query= "INSERT INTO timetable (id,value) VALUES (${id}, '${value}')"; // UNSAFE
您想知道,$value
是否包含任何引号字符?它是否包含任何其他会引起恶作剧的东西?您无法仅通过使用类型提示来阻止它成为 SQL 注入漏洞。
因此类型提示在使用 int
类型时可能有效,但在 string
类型时无效。其他类型呢?嗯,必须调查...
现在你打开了一堆蠕虫。您必须调查所有类型,并尝试提出完整的指导方针,说明哪些可以安全地插入到 SQL 中,哪些不能。您必须使这些指南足够清晰,以便您的软件开发团队的每个成员都可以遵循它们,并可以在代码审查期间使用它们。
即使您确实完美地编写了代码并针对每种类型使用了适当的 SQL 注入防御方法,但以后阅读代码的其他人也会感到困惑。 "Why aren't variables combined with SQL queries in the same way in different functions?" 他们会想知道。找出原因会占用他们的时间和注意力,使他们无法完成分配给他们的任何代码维护任务。请记住,在您开发此代码后,它将存在多年,并且其他软件开发人员需要维护它。使代码易于理解是值得的。
或者,您可以只使用参数。
SQL 查询参数适用于所有类型,您不必依赖 type-hinting。它们简单、有效,而且您可以始终如一地使用它们。
请停止寻找避免使用查询参数的方法。
打个比方:假设你是电工而不是软件开发人员。您听说电线应该绝缘以避免 short-circuits 的可能性。但出于某种原因,您不喜欢处理绝缘电线。
"I'll just put a shim in between the wires to keep them separated." 但你用作垫片的项目必须是 non-conductive 和 non-flammable.
什么样的垫片可以安全使用?伍德……不。金属……不。塑料……取决于塑料的类型。陶瓷...我不知道,得查一下什么的...
其他电工都会用奇怪的眼光看你。
"Just use insulated wires, are you trying to burn down this building?"