Php in_数组函数是阻止代码注入/sql注入的安全方法吗?

Php in_数组函数是阻止代码注入/sql注入的安全方法吗?,php,sql-injection,code-injection,Php,Sql Injection,Code Injection,如果我有一个php文件,它正在接收一个$_GET['value'],那么使用sql注入或代码注入启动php文件是否安全 if (in_array($_GET['value'], $allowed_values);) { /* normal page code handling the $_GET['value'] */ } else { unset($_GET['name']) } $allowed values显然是一个所有值的数组,我希望它对于$\u Get['value']是安

如果我有一个php文件,它正在接收一个$_GET['value'],那么使用sql注入或代码注入启动php文件是否安全

if (in_array($_GET['value'], $allowed_values);) 
{ /* normal page code handling the $_GET['value'] */ 

 } else { unset($_GET['name'])
 }

$allowed values显然是一个所有值的数组,我希望它对于$\u Get['value']是安全的。这还不安全吗?谢谢。

是的,这是一种常见且安全的技术,可用于无法使用查询参数的情况。例如,如果该值将用作表名或列名,则不能将其作为查询参数提供,必须将其直接替换为SQL字符串。这样的白名单是确保安全的推荐方法。

它取决于
$allowed\u values
数组中的值,以及如何将值插入SQL查询

例如:

$allowed_values = [ 'a word' ];

if (in_array($_GET['value'], $allowed_values)) {
  $sql = "SELECT * FROM mytable WHERE id = {$_GET['value']};";
}
绝对不安全。它会导致SQL:

SELECT * FROM mytable WHERE id = a word;
这是一个语法错误

为什么不使用SQL查询参数呢?那么你就不必担心它是否安全了。查询参数将值与SQL解析分开,因此任何类型的值都不可能导致SQL注入

您不必拥有
$allowed\u值
数组。您不必记得检查GET输入是否在数组中。你不必担心引用或逃避

的确,查询参数只适用于值,而不是带引号的字符串文字、带引号的日期时间文字或数字文字。如果您需要查询的其他部分是动态的,比如表名、列名或SQL关键字等,那么使用您正在展示的允许列表解决方案

但更常见的插值动态值的情况最好通过查询参数处理:

$sql = "SELECT * FROM mytable WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt-execute( [ $_GET['value'] ] );

让我们详细讨论一下这件事:

您的代码如下所示:

if (in_array($_GET['value'], $allowed_values);) { 
 ...........
 $sql = "SELECT * FROM mytable WHERE id = $_GET['value']";
 ...........

} 
else { 
  unset($_GET['name'])
}
现在让我们假设,您有一些值:

in_array()函数将只允许一些预定义值,您不能选择通过$\u GET接受自定义用户输入,但由于只允许预定义值,任何SQL命令在if语句中都是安全的

现在以$allowed_values数组为例:

$allowed_values = ['some details' , 'another details' ,3, ' 105; DROP TABLE mytable;', 22 , 'ok'];
如果这些数组值中有一个字符串可能具有潜在的SQL注入功能,那么就会出现问题。但我认为您不会将任何此类字符串放入数组$allowed_值中。(在上述示例中,索引3,'105;DROP TABLE mytable;'可以删除表mytable)。否则SQL命令将是安全的

现在,通过对任何SQL查询使用PDO,您可以在代码中添加额外的安全层。(在本例中,您不需要这样做,因为in_array()函数是100%安全的,除非您自己在数组中放入任何恶意代码,如我上面提到的示例所示)。但是对于其他类型的用户输入,您必须根据用户输入执行一些SQL查询,您可以使用PDO-prepared语句

PDO示例如下:

$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";

$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


$stmt = $conn->prepare("INSERT INTO photos (username, kname) VALUES (?, ?)");
$stmt->execute([  $username , $kname   ]);

有关详细信息,请尝试w3school链接:

,具体取决于
$allowed\u values
中的值和您拥有的实际代码,但可以。如果您可以通过这种方式限制输入,并且可能的值不能用于代码注入/sql注入,那么它就是save.Yes,但不是显式的。这是一种验证输入的形式,也是您应该经常做的事情,但在技术层面上它并不能阻止SQL注入。例如,如果您的一个允许值实际上是
”或1=1--
,则与使用参数实际禁止SQL注入相比,它仍然会被注入。您需要养成这样的习惯,它可以帮助您解决问题。您将获得积分,并鼓励其他人帮助您。完美答案。简洁明了。谢谢你,帕哈里先生,谢谢你,这是你的回答和卡温先生的回答之间的一条真正的纽带。他的回答非常简洁,但涵盖了所有领域,而你的回答在某些方面更为详细。各有所长。无法选择。简明扼要地说:in_array()是最安全的,但您只接受预定义的输入。如果“$allowed_values”数组下没有任何内容,则if语句将不会通过。但是如果您想在不知道put是什么的地方获取用户输入:使用REGEX和PDO Prepare语句来保护sql注入。