2013-08-25 2 views
11

Я учусь об исключении SQL-инъекций, и я немного смущен.Что делает bind_param?

При использовании bind_param я не понимаю цели. На странице вручную, я нашел этот пример:

$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); 
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent); 

$code = 'DEU'; 
$language = 'Bavarian'; 
$official = "F"; 
$percent = 11.2; 

Теперь, предполагая, что эти 4 переменные были введены пользователем, я не понимаю, как это предотвращает инъекции SQL. По моему мнению, они все еще могут вводить все, что захотят.

Я также не могу найти объяснение для 'sssd'. Что оно делает? Это то, что делает его безопасным?

Заключительный вопрос: Я прочитал по другому вопросу, что mysqli_real_escape_string устарел, но он не говорит об этом в руководстве. Как он устарел? Не может ли он почему-то избежать специальных символов?

Примечание: Этот вопрос объясняет, что делает bind_param, но я до сих пор не понимаю, почему он безопаснее или более защищен. Bind_param explanation

+6

'sssd' переводит строку, строку, строку, двойную. «По моему мнению, они все еще могут вводить туда, где они хотят». Правильно. Но SQL не анализируется в этих четырех переменных. –

+1

По ссылке, которую вы отправили, вы забыли прочитать http://www.php.net/manual/en/mysqli-stmt.bind-param.php, которая подробно описывает строку 'types A, содержащую один или несколько символов, которые определяют типы для соответствующих переменных связывания: ' – Prix

+1

@DaveChen« SQL не разбирается »Это означает, что они все равно могут вставлять SQL, он просто не будет прочитан как SQL, правильно? Означает ли это, что если бы у меня не было проверки формы, они могли бы просто ввести команды SQL в мою базу данных/в поле, но это не имело бы значения, потому что SQL не анализируется? – EveyPortman

ответ

12

Теперь, предполагая, что эти 4 переменные были введены пользователем, я не понимаю, как это предотвращает инъекции SQL. По моему мнению, они все равно могут добавить туда все, что захотят.

Основной принцип есть, используя подготовленное заявление, которое предназначено для отправки безопасного запроса к БД сервера, это может быть сделано путем избежать ввода данных пользователем, который не является частью реального запроса, а также проверки запроса без каких-либо (where), чтобы проверить правильность запроса перед использованием любых параметров.

С этого вопроса: PDO sends raw query to MySQL while Mysqli sends prepared query, both produce the same result

$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) { 
$stmt->bind_param("i", $user); 
$user = "''1''"; 

сервера журналы:

130802 23:39:39 175 Connect ****@localhost on testdb 
    175 Prepare SELECT * FROM users WHERE username =? 
    175 Execute SELECT * FROM users WHERE username =0 
    175 Quit 

, используя подготовленный оператор, сервер БД будет проверить запрос без какого-либо параметра, на данном этапе, ошибки могут быть обнаружен перед связыванием любого параметра, тогда, если запрос был действителен, параметры также будут отправляться на сервер для завершения запроса.

С PHP Manual http://php.net/manual/en/mysqli.quickstart.prepared-statements.php:

Экранирования и инъекция SQL

Связанных переменными будет экранирован сервером автоматически. Сервер вставляет свои экранированные значения в соответствующие места в шаблон оператора перед выполнением. Для сервера для типа связанной переменной необходимо указать подсказку для создания соответствующего преобразования . См. Функцию mysqli_stmt_bind_param() для получения дополнительной информации .

..

Я также не могу найти объяснение для 'SSSD' там. Что делает ?Это то, что делает его безопасным?

Ответ здесь: http://php.net/manual/en/mysqli-stmt.bind-param.php

i 
corresponding variable has type integer 

d 
corresponding variable has type double 

s 
corresponding variable has type string 

b 
corresponding variable is a blob and will be sent in packets 

Заключительный вопрос: Я читал на другой вопрос, что mysqli_real_escape_string является устаревшим, но это не говорит о том, что в руководства. Как он устарел? Не может ли он почему-то избежать специальных символов ?

Можете ли вы дать ссылку? Я думаю, вы неправильно поняли (mysql_real_escape_string())

+0

Спасибо, да, я, должно быть, прочитал mysql как msqli. – EveyPortman

+0

@EveyPortman обратите внимание, что этот ответ неправильный. –

+3

@YourCommonSense: опубликуйте правильный ответ и упомянули, что не так в моем ответе. –

10

С помощью подготовленных операторов вы отделяете SQL-запросы от введенных пользователем данных. Вместо входных данных вы помещаете заполнители ('?' Char) в свой SQL-запрос. Затем вы отправляете запрос на сервер СУБД (например, MySQL) с помощью метода «mysqli :: prepare». Поэтому сервер проверяет, что все в порядке, и если да, то ожидает входных данных. К настоящему времени он уже знает ваш запрос. Просто он должен ждать ввода данных для привязки к запросу.

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

ИНАЧЕ ...

Фактическая цель использовать подготовленное заявление в SQL, чтобы сократить стоимость обработки запросов, а не отдельные данные из запроса. Именно так оно используется сейчас, а не как оно предназначено для использования в первую очередь.

«sssd» означает «строка», «строка», «строка» и «двойной». Фактически: $ code - это строка, $ language - строка, $ official - строка, а $ percent - двойной тип.

mysqli_real_escape_string не устарел, но mysql_real_escape_string устарел (первый из них - mysqlI, где я обозначаю «улучшенный»).