Оглавление

5.4. Обработка результата запроса

Для обработки результата запроса используются следующие функции:
□ mysql_num_rows(<Идентификатор результата>) возвращает количество записей в результате:

 

if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
$res = mysql_query('SELECT * FROM `City`');
echo mysql_num_rows($res);
// Выведет: 2
mysql_close($db); // Закрываем соединение
}

else {
echo "Не удалось установить подключение к базе данных";
}

□ mysql_num_fields(<Идентификатор результата>) возвращает количество полей в результате:


if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
$res = mysql_query('SELECT * FROM `City`');
echo mysql_num_fields($res);
// Выведет: 2
mysql_close($db); // Закрываем соединение
}
else {
echo "Не удалось установить подключение к базе данных";
}


□ mysql_result() позволяет получить доступ к отдельному полю по указанному номеру строки. Нумерация строк начинается с нуля:


if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
$count = mysql_num_rows($res);
for ($i=0; $i<$count; $i++) {
$id = mysql_result($res, $i, "id_City");
$city = mysql_result($res, $i, "City");
echo "$id - $city<br>";
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


Этот код выведет
1 - Санкт-Петербург
2 - Москва

 

□ mysql_fetch_array(<Идентификатор результата>) возвращает результат в виде списка и ассоциативного массива:

if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_array($res)) {
echo $pole['id_City'] . ' – ' . $pole['City'] . '<br>';
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


или

if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_array($res)) {
echo $pole[0] . ' – ' . $pole[1] . '<br>';
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


□ mysql_fetch_row(<Идентификатор результата>) возвращает результат в виде списка:


if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_row($res)) {
echo $pole[0] . ' – ' . $pole[1] . '<br>';
}

mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


□ mysql_fetch_assoc(<Идентификатор результата>) возвращает результат в виде ассоциативного массива:


if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_assoc($res)) {
echo $pole['id_City'] . ' – ' . $pole['City'] . '<br>';
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


□ mysql_fetch_object(<Идентификатор результата>) возвращает результат в виде объекта:


if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_object($res)) {
echo $pole->id_City . ' – ' . $pole->City . '<br>';
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


□ mysql_real_escape_string(<Строка>) экранирует все специальные символы в строке, учитывая кодировку соединения. Возвращает строку, которую можно безопасно использовать в SQL-запросах. (1)


Если в файле php.ini включена директива magic_quotes_gpc, то следует удалить автоматически добавленные экранирующие обратные косые черты, а затем воспользоваться функцией mysql_real_escape_string():  (2)


$new_city = "Д'Арк";
if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
// Если директива magic_quotes_gpc включена,
// то удаляем защитные косые черты
if (get_magic_quotes_gpc()) {
$new_city = stripcslashes($new_city);
}
// Экранируем спецсимволы
$new_city = mysql_real_escape_string($new_city);
mysql_query("INSERT INTO `City` VALUES(NULL, '$new_city')");
$res = mysql_query('SELECT * FROM `City`');
while ($pole = mysql_fetch_object($res)) {
echo $pole->id_City . ' – ' . $pole->City . '<br>';
}
mysql_close($db);
}
else {
echo "Не удалось установить подключение к базе данных";
}


 

В качестве примера рассмотрим проблему, возникающую, если не применить функцию mysql_real_escape_string() для входных данных.

 

Создадим таблицу user и добавим в нее две записи:
CREATE TABLE `user` (
`id_user` MEDIUMINT(9) AUTO_INCREMENT,
`login` CHAR(50),
`passw` CHAR(32),
PRIMARY KEY (`id_user`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
INSERT INTO `user` VALUES (NULL, 'Admin', '123');
INSERT INTO `user` VALUES (NULL, 'Nik', '456');


Теперь инсценируем вход злоумышленника в систему под логином администратора. При этом злоумышленник даже не должен знать его пароль.


<?php
// Никогда так не делайте!!!
// Такие данные пришли из формы:
$_POST['login'] = "' OR ''='";
$_POST['passw'] = "' OR ''='";
$login = $_POST['login'];
$passw = $_POST['passw'];
if ($db = @mysql_connect("localhost", "root", "123456")) {
mysql_select_db("tests");
mysql_query("SET NAMES cp1251");
$query = "SELECT * FROM `user` WHERE `login`='$login' ";
$query .= "AND `passw`='$passw'";
echo $query . '<br>';
$res = mysql_query($query);
if (mysql_num_rows($res) > 0) {
echo 'Полный доступ в систему!!!<br>';
}
while ($pole = mysql_fetch_object($res)) {
echo $pole->login . '<br>';
}
mysql_close($db);
}

else {
echo "Не удалось установить подключение к базе данных";
}
?>


Введя указанные в начале примера строки в форме, злоумышленник получит
SELECT * FROM `user` WHERE `login`='' OR ''='' AND `passw`='' OR ''=''

 

Полный доступ в систему!!!
Admin
Nik
Итак, злоумышленник вошел в систему, не зная пароля. В данном примере, так как учетная запись администратора расположена на первой позиции, мы вошли под записью администратора. Нам просто повезло. А теперь войдем в систему именно под учетной записью администратора. Для этого входящие
данные изменим на:

$_POST['login'] = "Admin'/*";
$_POST['passw'] = "*/ '";

 
После выполнения скрипта получим следующий результат:
SELECT * FROM `user` WHERE `login`='Admin'/*' AND `passw`='*/ ''

 
Полный доступ в систему!!!
Admin

 
Как видно из результата, мы являемся администратором. Все что расположено между /* и */ является комментарием. В итоге SQL-запрос будет выглядеть так:
SELECT * FROM `user` WHERE `login`='Admin' ''

 
Никакой проверки пароля в данном случае вообще не производится. Достаточно знать логин пользователя и можно войти без пароля.


Если бы данные были обработаны функцией mysql_real_escape_string(), то такого бы не случилось:


$login = mysql_real_escape_string($login);
$passw = mysql_real_escape_string($passw);
$query = "SELECT * FROM `user` WHERE `login`='$login' ";
$query .= "AND `passw`='$passw'";
echo $query . '<br>';


В первом случае скрипт выведет только
SELECT * FROM user WHERE login='\' OR \'\'=\'' AND passw='\' OR \'\'=\''

А во втором
SELECT * FROM `user` WHERE `login`='Admin\'/*' AND `passw`='*/ \''

 
В результате все опасные символы были экранированы. (3)


Примечания:
  • Функцию можно использовать только после подключения к базе данных. В противном случае получите сообщение об ошибке.
  • Никогда напрямую не передавайте в SQL-запрос данные, полученные из полей формы. Это потенциальная угроза безопасности. Всегда применяйте функцию mysql_real_escape_string().
  • Выводить код SQL напрямую в Web-страницу также не рекомендуется, так как это дает злоумышленнику лишнюю информацию о структуре базы данных.
Комментарии принадлежат их авторам. Мы не несем ответственности за их содержание.
Отправитель Нити