mysqli_query () не поддерживает мультизапрос по умолчанию. Для этого есть отдельная функция: mysqli_multi_query () .
Внедрение SQL - это не только запуск нескольких операторов, несмотря на знаменитый мультфильм XKCD .
Ваш код имеет плохую уязвимость внедрения SQL. Считаете ли вы, что использование prepare()
каким-то образом делает запрос безопасным, даже если вы интерполируете содержимое из ваших данных запроса $ _POST непосредственно в строку SQL?
Ваш код такой:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
/* execute statement */
$stmt->execute();
...
Небезопасный ввод данных может легко привести к неправильному введению SQL. Это может быть даже невинно, но все равно приводит к проблемам. Предположим, например, что поиск: O'Reilly
. Копирование этого значения непосредственно в ваш SQL приведет к следующему запросу:
SELECT username, email FROM Members where username = 'O'Reilly'
Видите несоответствующие '
цитаты? Это не принесет ничего плохого, но вызовет сбой запроса, потому что несбалансированные кавычки создают синтаксическую ошибку.
Использование prepare()
не исправляет случайные синтаксические ошибки и не защищает от копирования вредоносного содержимого, которое изменяет синтаксис запроса.
Чтобы защитить как от случайного, так и от вредоносного внедрения SQL, вы должны использовать связанные параметры, такие как:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('s', $searchterm);
/* execute statement */
$stmt->execute();
...
Связанные параметры не копируются в запрос SQL. Они отправляются на сервер базы данных отдельно и никогда не объединяются с запросом до тех пор, пока после *1029* не будет проанализирован, и поэтому не может вызвать проблемы с синтаксисом.
Что касается вашего вопроса о mysqli::query()
, вы можете использовать его, если ваш запрос SQL не нуждается в связанных параметрах.
Ваш комментарий:
... уязвимы для инъекций, поэтому я могу показать студентам, какой вред может нанести злонамеренная атака.
Вот пример:
Несколько лет назад я был инструктором по SQL, и во время одного из моих тренингов в компании я говорил о внедрении SQL. Один из участников сказал: «Хорошо, покажи мне атаку SQL-инъекцией». Он вручил мне свой ноутбук. Браузер был открыт для экрана входа в систему для его сайта (это был только его тестовый сайт, а не настоящий рабочий сайт). Форма входа была простой, с полями для имени пользователя и пароля.
![enter image description here](https://i.stack.imgur.com/t1Hco.png)
Я никогда не видел его код, который обрабатывает форму входа, но я предположил, что форма была обработана некоторым кодом, как большинство небезопасных веб-сайтов:
$user = $_POST['user'];
$password = $_POST['password'];
$sql = "SELECT * FROM accounts WHERE user = '$user' AND password = '$password'";
// execute this query.
// if it returns more than zero rows, then the user and password
// entered into the form match an account's credentials, and the
// client should be logged in.
(Это было мое образованное предположение о его коде, я еще не видел код.)
Мне потребовалось 5 секунд, чтобы подумать о логике, и я ввел логическое выражение в форму входа для имени пользователя, а для пароля я набрал случайные символы мусора.
Затем я вошел в его аккаунт - , не зная и даже не пытаясь угадать его пароль.
Я не буду давать точное логическое выражение, которое я использовал, но если вы понимаете базовый приоритет булевых операторов, описанный в любом классе Discrete Math, вы сможете понять его.