Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > проверка данных, введенных пользователем


Автор: Splendid 17.10.2007, 13:12
Подскажите, есть ли какой-нибудь стандартный набор проверки данных, введенных пользователем (которые потом подставляются в запрос к базе) на "безопасность", т.е. чтобы он там не навводил чего-нибудь нехорошего.
Много кусков понаходила по этому поводу, но вот хотелось бы иметь полную картину, может кто-нибудь поделится знаниями?
Списком запрещенных для ввода символов?
и еще, где могут быть "дыры" по безопасности в скрипте поиска, например? При использовании каких функций?

Автор: flashaa 17.10.2007, 14:13
Для базы обычно опасность представляет SQL - инъекция - вставка куска запроса из данных пользователя в ваш запрос.
К примеру: 
Код

$num = $_GET['num'];
mysql_query('UPDATE tbl SET field = ' . $num . ' );


Юзер вводит в запрос что-то типа этого 
Код

1; DROP TABLE tbl


и запрос уже получается следующего вида:
Код

mysql_query('UPDATE tbl SET field = 1; SHOW tbl;' );


И получается уже 2 запроса, второй из которых вредительский.

Можно ввести кавычки, это немного усложнит задачу:
Код

mysql_query('UPDATE tbl SET field = "' . $num . '"' );

// после подстановки переменной, запрос будет выглядеть так:
mysql_query('UPDATE tbl SET field = "1; SHOW tbl; " ');

В этом случае значение будет воспринято как строка и проблем с таким простым хакерским запросом не будет.

Но стоит злоумышленнику хитро ввести кавычки в свой запрос и тогда ваши кавычки перестанут действовать.
Код

$num = ' 1"; DROP TABLE tbl; "1 = 1 ';
mysql_query('UPDATE tbl SET field = "1"; DROP TABLE tbl; "1 = 1" ');

Мы снова хакнуты.

Встает вопрос об экранировании спецсимволом, т.е. чтобы кавычки считались частью текста, а не указанием интерпретатору о конце, либо начале строки. Как известно внутри строки PHP любой спец-символ теряет свое специальное значение, если перед ним поставлен обратный слеш. 

Для этого специально придумана функция addslashes - http://ru2.php.net/manual/ru/function.addslashes.php

Переписываем код:
Код

mysql_query('UPDATE tbl SET field = "' . addslashes($num) . '"' );


Теперь злоумышленник не может завершать наши запросы и все, что он введет в переменную $num будет гарантированно считаться строкой.. 
Примерно так. Я знаю, что существуют ещё хаки со сменой кодировок, когда опасные символы все-таки проходят, но только по наслышке, если кто выскажится по этому поводу буду признателен.

Так же на счет экранирования: в MySQL, насколько мне известно экранирующим символом как раз и является наш слеш "\". В некоторых других БД это не так, и стоит предусмотреть другой метод.

А вообще используйте библиотеку DbSimple для работы с БД и все будет просто, понятно и безопасно.
http://dklab.ru/lib/DbSimple/

Автор: SelenIT 17.10.2007, 14:42
Цитата(Splendid @  17.10.2007,  13:12 Найти цитируемый пост)
Списком запрещенных для ввода символов?

Их нет. Вводить можно все, база поймет и обработает как надо. Если осторожно.
Цитата(flashaa @  17.10.2007,  14:13 Найти цитируемый пост)
и запрос уже получается следующего вида:
Код

mysql_query('UPDATE tbl SET field = 1; SHOW tbl;' );

И получается уже 2 запроса, второй из которых вредительский.

Конкретно этот случай безопасен - mysql_query не умеет выполнять больше одного запроса сразу. Но mysqli уже умеет, равно как mssql_query  и т.п.. Да и один запрос можно хакнуть - например, в обычный запрос авторизации "SELECT user_id FROM users WHERE login='$login' AND password='$password'" можно впихнуть $password="' OR '1'='1" и получить права любого юзера...

Цитата(flashaa @  17.10.2007,  14:13 Найти цитируемый пост)
Для этого специально придумана функция addslashes

Для этого же придуманы http://www.php.net/manual/ru/ref.info.php#ini.magic-quotes-gpc и много чего еще, что призвано "защитить невежественного юзера от нечаянной глупости", но на деле лишь рождает путаницу. Исчерпывающая, имхо, статья по экранированию кавычек и не только - http://phpfaq.ru/slash. А для экранирования данных, подставляемых в запросы MySQL, надо использовать не древний addslashes, а специализированную ф-цию http://php.net/mysql_real_escape_string (которая, кроме прочего, дружит с юникодом).
Цитата(Splendid @  17.10.2007,  13:12 Найти цитируемый пост)
где могут быть "дыры" по безопасности в скрипте поиска, например?

При выводе поискового запроса в результатах - злоумышленник может вставить туда HTML-код (вплоть до скриптов). Поэтому все, что пришло от юзера, перед выводом нужно прогонять через http://php.net/htmlspecialchars.

Автор: Splendid 18.10.2007, 12:43
Спасибо огромное, буду иметь ввиду!
Если есть еще какие-нибудь "моменты", пишите, пожалуйста!

Автор: sw04 20.10.2007, 10:31
ограничения по количеству возможных символов - substr
мощная функция mysql_real_escape_string
иногда приходится без заморачиваний - если у тебя входная переменная число, то используй intval.
при этом для ограничения раскрытия путей, советую использовать mysql_result и mysql_num_rows.
в книжках по пхп они достаточно ярко описаны.

Автор: SelenIT 21.10.2007, 02:07
Цитата(sw04 @  20.10.2007,  10:31 Найти цитируемый пост)
при этом для ограничения раскрытия путей, советую использовать mysql_result и mysql_num_rows


sw04, какое отношение имеют mysql_* к раскрытию путей?

Автор: sw04 21.10.2007, 11:43
Цитата(SelenIT @  21.10.2007,  05:07 Найти цитируемый пост)
какое отношение имеют mysql_* к раскрытию путей? 

например, mysql_query получаем не одну строку, как надо , а 0. ничего не удовлетворяет запросу, тогда выходит notice, где указывается путь до скрипта и сторка, где расположен mysql_fetch_*

Автор: SelenIT 21.10.2007, 22:34
Цитата(sw04 @  21.10.2007,  11:43 Найти цитируемый пост)
mysql_query получаем не одну строку, как надо , а 0. ничего не удовлетворяет запросу, тогда выходит notice

Злостный поклёп на пэхэпэшечку! Во-первых, обычная конструкция 
Код

$result = mysql_query($query);
while ($row = mysql_fetch_row($result)) { // либо mysql_fetch_assoc, смотря по логике скрипта
   do_something_with($row);
}
не вызывает никаких нотайсов при пустом рекордсете, и уж никак не дает повода использовать устаревший и тормозной mysql_result smile.  Обращение к несуществующей переменной - результат непродуманности алгоритма/криворукости его автора, и никак не вытекает из использования функций как таковых. Во-вторых, display_errors="on" в production-окружении - само по себе грубая ошибка, я полагаю, что человек, всерьез задумавшийся о безопасности скриптов, такого попросту не допустит smile.

Ну и наконец, грамотное планирование алгоритма, в т.ч. обработки нештатных ситуаций и аккуратное сообщение о них (минимальное - пользователю на экран и подробное - разработчику в лог и/или сразу на e-mail;) - это отдельная большая тема, о которой не рассказать в двух словах. Об этом написаны большие статьи и толстые монографии. По большому счету, проверка ввода и политика в отношении display_errors/error_reporting - лишь два частных аспекта этой темы, а mysql тут вообще ни при чем.

Автор: flashaa 21.10.2007, 23:16
Selenit, согласен. + пользуем try - catch. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)