Как избежать SQL-инъекций с подготовкой и выполнением - PullRequest
3 голосов
/ 07 марта 2019

Строка кода типа

my $sql_query = "SELECT * FROM Users WHERE user='$user';";

может привести к уязвимости SQL-инъекций в вашей программе. Чтобы избежать этого, можно использовать что-то вроде

my $sth = $dbh->prepare("SELECT * FROM Users WHERE user='?';");
$dbh->execute($user);

Однако в коде, над которым я сейчас работаю, используется следующее:

$sql_query = "SELECT * FROM Users WHERE user='" . $user . "';";
$dbh->prepare($sql_query);
$dbh->execute();

Это на самом деле работает? Если да, есть ли различия в том, что я сделал бы? Каковы преимущества и недостатки?

1 Ответ

6 голосов
/ 07 марта 2019
my $sth = $dbh->prepare("SELECT * FROM Users WHERE user='?'");

Это не сработает, потому что он ищет буквальный символ '?', а не параметр. Если вы попытаетесь отправить значение для параметра, MySQL будет выглядеть так: «Что вы хотите, чтобы я сделал с этим?» потому что запрос не имеет параметра-заполнителя.

Если вы хотите использовать параметр, вы НЕ должны помещать местозаполнитель параметра в разделители строк в запросе SQL, даже если параметр будет принимать строковое значение или значение даты / времени:

my $sth = $dbh->prepare("SELECT * FROM Users WHERE user=?");

Следующий пример:

$sql_query = "SELECT * FROM Users WHERE user='" . $user . "'";
$dbh->prepare($sql_query);
$dbh->execute();

Это запустит запрос, но это НЕ безопасно. Вы можете подготовить любой запрос, даже если он не имеет параметров.

Использование prepare() не делает запросы безопасными от внедрения SQL. Что делает его более безопасным, так это использование параметров для объединения динамических значений вместо конкатенации строк, как в этом примере.

Но использование параметров требует использования prepare().

PS: Вам не нужно ставить ; в конце ваших запросов SQL, когда вы запускаете их по одному программно. Разделитель необходим только в том случае, если вы выполняете несколько запросов, например, в скрипте SQL или в хранимой процедуре. В ваших примерах ; безвреден, но MySQL этого не требует, и просто проигнорирует.

...