提问人:Maximilian Travis 提问时间:8/8/2020 更新时间:8/8/2020 访问量:231
in_array 函数是阻止代码注入/sql 注入的安全方法吗?
Is the in_array function a safe way of blocking code injection/sql 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值显然是所有值的数组,我期望这些值对 $_Get['value'] 是安全的。这仍然不安全吗?谢谢。
答:
是的,这是一种常见且安全的技术,可用于无法使用查询参数的情况。例如,如果该值将用作表名或列名,则不能将其作为查询参数提供,则必须将其直接替换为 SQL 字符串。像这样的白名单是确保安全的建议方法。
这取决于数组中的值,以及如何将值插值到 SQL 查询中。$allowed_values
例如:
$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 注入。
您不必拥有数组。您不必记得检查 GET 输入是否在数组中。您不必担心引用或逃避。$allowed_values
确实,查询参数仅适用于值,即代替带引号的字符串文本或带引号的日期时间文本或数字文本。如果您需要查询的其他部分是动态的,例如表名或列名或 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() 函数将只允许一些预定义的值,您不能选择以 $_GET 的价格接受自定义用户输入,但由于只允许预定义值,因此任何 SQL 命令在 if 语句中都是安全的。
现在以 $allowed_values 数组为例:
$allowed_values = ['some details' , 'another details' ,3, ' 105; DROP TABLE mytable;', 22 , 'ok'];
如果这些数组值中的任何一个具有可能具有潜在 SQL 注入功能的字符串,则会出现问题。但我认为你不会把任何这样的字符串放在数组 $allowed_values 中。(在上面提到的例子中,索引 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 链接: https://www.w3schools.com/php/php_mysql_prepared_statements.asp
评论
$allowed_values
' or 1=1--