Запрос на ввод MySQL

Я знаком с подготовленными заявлениями, и я знаю, что они лучше всего подходят для защиты от MySQL-инъекций. Но мне интересно, как это заявление PHP / MySQL может подвергаться риску инъекции:

$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".$_POST['name']."';"); 

Мне кажется, что вход пользователя будет содержаться внутри одинарных кавычек. Можете ли вы выполнить несколько запросов в одном операторе mysqli_query ?

Кроме того, сделать выше безопасным так же просто, как это …

 $result = mysqli_query($db,"SELECT name FROM users WHERE id = '".mysqli_real_escape_string($_POST['name'])."';"); 

Мне кажется, что вход пользователя будет содержаться внутри одиночных кавычек

Это произойдет, если вы не включите одинарные кавычки в опубликованное name , что позволит вам выйти из кавычек. Например, опубликуйте имя как:

 ' or 1 or ' 

Предложение WHERE становится:

 WHERE id = '' or 1 or ''; 

Это будет соответствовать и извлекать все строки в таблице из-за одной or 1 части. Как вы можете видеть, он вырывается из кавычек для ввода некоторого SQL, затем он возвращается в кавычки, чтобы сделать запрос действительным.

Можете ли вы выполнить несколько запросов в одном операторе mysqli_query ?

Нет, но если он был выполнен с помощью mysqli_multi_query тогда да, вы могли бы добавить несколько запросов к концу.

делает вышеперечисленное безопасным так же просто, как mysqli_real_escape_string ?

В общем, да, но подготовленное заявление было бы лучше. Используя escaping, WHERE станет (используя мой пример выше):

 WHERE id = '\' or 1 or \''; 

Это уже не уязвимо, потому что кавычки не могут быть разбиты и будут соответствовать только строкам, если name буквально соответствует ' or 1 or ' что явно маловероятно.

Мне кажется, что вход пользователя будет содержаться внутри одиночных кавычек

Все, что должен сделать атакующий, – это поставить одну цитату внутри имени POST, и ее больше не будет.

 name=' OR 1=1 

Кроме того, сделать вышеуказанный сейф так же просто, как это

Это выглядит хорошо … но мне больно. Используйте подготовленные заявления. Их гораздо легче читать, чем SQL, построенных путем объединения строк вместе.

Основное объяснение:

Если вы просто введете $_POST['name'] в запрос в соответствии с вашим первым примером, результирующая строка SQL будет недействительной, если переменная name содержит одиночный символ кавычки.

Это будет немедленно раздражать любого, кто по имени О'Брайен, или что-то подобное.

Но это может быть использовано хакером, который может изменить свое «имя», чтобы включить действительный код SQL после одиночной кавычки. Это может быть любой допустимый SQL, позволяющий хакеру что-либо делать с вашей БД или запрашивать что-нибудь от него. То, что он может сделать, будет зависеть от других факторов вашего кода, но достаточно сказать, что даже в лучшем случае он мог бы сделать некоторые довольно разрушительные вещи.

Чтобы ответить на ваш второй вопрос: Да. mysqli_real_escape_string() с помощью mysqli_real_escape_string() уменьшит эту проблему.

Однако, чтобы сделать что-то еще на один шаг, вам также может потребоваться расследовать использование подготовленных запросов, что является функцией расширения mysqli . Это может сделать ваш код намного опрятным, поскольку он избегает необходимости использовать это mysqli_real_escape_string() длинное mysqli_real_escape_string() функции mysqli_real_escape_string() повсюду. Он также имеет другие преимущества, такие как улучшенное кэширование запросов.

Надеюсь, что это поможет ответить на вопрос.

Что, если я передал следующее значение для $_POST['name'] ?

 '; DELETE FROM users WHERE name <> ' 

Я бы закрыл первую одинарную цитату, а затем представил повреждающий запрос, который в конце концов имеет только одну открытую цитату, которая будет закрыта одинарной цитатой в исходном запросе.

Второй запрос в порядке. Хотя вы действительно должны рассмотреть использование подготовленных операторов (которые поддерживаются mysqli)

Если вы используете mysqli вы всегда должны использовать метод SQL-заполнителя для этого. Функции экранирования – это трудный путь.

 $stmt = $db->prepare("SELECT name FROM users WHERE id = ?"); $stmt->bind_param('i', $_POST['name']); $stmt->execute(); 

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