У меня в голове появилась кощунственная мысль засунуть кусочек кода в скрипт с библиотекой функций/классов чтобы он проводил через себя все 3 массива куков, пост и гет. С каждым элементом он производил определенные действия , а потом засовывал их обратно в массив. Вопрос насколько это нужно и сильно ли это нагрузит все?
Скрипт составить не проблема, вопрос в том, нужно ли это делать, т.е. предпочтительней "мыть" входящие данные на входе по-отдельности или все сразу. Исходя из вышестоящего поста можно стелать вывод, что путь наибольшей головной боли предпочтительней
intro В этой небольшой статье я расскажу о защите о всем нам известной уязвимости SQL-injection. Данной уязвимости подвержено подавляющее большинство сайтов в сети. Суть уязвимости заключается в отсутствии фильтрации спецсимволов в параметрах, передаваемых в запросах к БД. Уязвимость позволяет злоумышленнику выполнять запросы к БД… Да лан, чё я рассказываю. В разделе статьи полно информации по SQL-injection и я изобретать велосипед не буду. Ну что ж, перейдём к сути… Метод №1 – Фильтрация Этот метод заключается в фильтрации спецсимволов с помощью стандартной функции preg_match(). Данная функция будет обрабатывать параметры, передаваемые скрипту от пользователя, на соответствие параметрам, которые должны быть в запросе. Вот кусок уязвимого скрипта: PHP: … if(!empty($_GET['id'])) { /*Получение нужной статьи из БД*/ $query = "SELECT * FROM articles WHERE id = '$_GET[id]'"; $result_query = mysql_query($query); if (!$result_query) exit("Bad parametr"); if ($article = mysql_fetch_array($result_query)) { … А вот тот же код, только с использованием функции preg_match(): PHP: … if(!empty($_GET['id'])) { /*Проверка переданного параметра*/ if (preg_match("|^[\d]{1,3}$|", $_GET['id'])) { /*Получение из БД нужной статьи*/ $query = "SELECT * FROM articles WHERE id = '$_GET[id]'"; $result_query = mysql_query($query); if (!$result_query) exit("Bad parametr"); if ($article = mysql_fetch_array($result_query)) { … else { /*Получение из БД всех статей*/ $query = "SELECT * FROM articles"; $result_query = mysql_query($query); if (!$result_query) exit("Bad parametr"); while ($article = mysql_fetch_array($result_query)) { … Согласитесь, не сложно написать пару лишних строк в скрипт, которые смогут защитить ваш сайт от атаки. Некоторые перци обрабатывают параметр функцией mysql_escape_ptring(), она похожа на addslashes(). Лично я такой подход не уважаю. Этот способ можно использовать лиш как способ записи корректных SQL запросов и не более того. Многие используют фцнкцию str_replace() которая вырезает все спецсимволы в параметре. Но при использование данной функции запрос всё равно будет выполнен с ложными данными, и вызовет туеву хучу ошибок. Способ №2 – создание собственной функции обращения к БД Согласитесь, каждый раз добавлять preg_match достаточно нудное занятие, есть способ как этого избежать. Можно написать свою функцию , которая будет отправлять запросы к БД. Вот пример от Дмитрия Котерова, библиотека содержащая в себе функцию для защиты нашего скрипта. Суть её работы в том, что она заменяет стандартную и всем нам до боли известную функцию mysql_query() своей mysql_qw(), т.е. в либе он создал функцию, заменяющую mysql_query, в которую сразу встроена проверка спецсимволов, а так же HTML-тэгов. Данный скрипт защищает как от SQL-injection, так и от XSS. Вот код библиотеки: PHP: <?php ## Простейшая функция для работы с placeholder-ами. // result-set mysql_qw($connection_id, $query, $arg1, $arg2, ...) // - или - // result-set mysql_qw($query, $arg1, $arg2, ...) // Функция выполняет запрос к MySQL через соединение, заданное как // $connection_id (если не указано, то через последнее открытое). // Параметр $query может содержать подстановочные знаки ?, // вместо которых будут подставлены соответствующие значения // аргументов $arg1, $arg2 и т.д. (по порядку), экранированные и // заключенные в апострофы. function mysql_qw() { // Получаем все аргументы функции. $args = func_get_args(); // Если первый параметр имеет тип "ресурс", то это ID соединения. $conn = null; if (is_resource($args[0])) $conn = array_shift($args); // Формируем запрос по шаблону. $query = call_user_func_array("mysql_make_qw", $args); // Вызываем SQL-функцию. return $conn!==null? mysql_query($query, $conn) : mysql_query($query); } // string mysql_make_qw($query, $arg1, $arg2, ...) // Данная функция формирует SQL-запрос по шаблону $query, // содержащему placeholder-ы. function mysql_make_qw() { $args = func_get_args(); // Получаем в $tmpl ССЫЛКУ на шаблон запроса. $tmpl =& $args[0]; $tmpl = str_replace("%", "%%", $tmpl); $tmpl = str_replace("?", "%s", $tmpl); // После этого $args[0] также окажется измененным. // Теперь экранируем все аргументы, кроме первого. foreach ($args as $i=>$v) { if (!$i) continue; // это шаблон if (is_int($v)) continue; // целые числа не нужно экранировать $args[$i] = "'".mysql_escape_string($v)."'"; } // На всякий случай запорняем 20 последних аргументов недопустимыми // значениями, чтобы в случае, если число "?" превышает количество // параметров, выдавалась ошибка SQL-запроса (поможет при отладке). for ($i=$c=count($args)-1; $i<$c+20; $i++) $args[$i+1] = "UNKNOWN_PLACEHOLDER_$i"; // Формируем SQL-запрос. return call_user_func_array("sprintf", $args); } ?> Используется он так PHP: include_once( "./mysq_qw.php" ); … if(!empty($_GET['id'])) { /*Получение нужной статьи из БД*/ $query = "SELECT * FROM articles WHERE id = '$_GET[id]'"; $result_query = mysql_qw($query); if (!$result_query) exit("Bad parametr"); if ($article = mysql_fetch_array($result_query)) { … Конечно он староват, но работает до сих пор… Способ №3 – Использование mod_rewrite Этот способ заключается в использовании модуля Апача под названием mod_rewrite. И так, как же мы его будем использовать??? Все знаю как данные передаются скрипту методом GET (www.site.ru/script.php?id=1), где id содержит параметры для обращения к БД. С использование mod_rewrite можно выше приведённой ссылке придать более человеческий вид (Например: www.site.ru/script_1.html). Для этого на нужно в веб-каталоге сервера (Например: /home/site/www) создать файл .htaccess со следующим кодом: Code: RewriteEngine on Options +FollowSymlinks RewriteBase / RewriteRule ^.htaccess$ - [F] Таким образом мы будем запускать модуль. Теперь перейдем к замене ссылок. Добавим в конец .htaccess следующую строку: Code: RewriteRule http://www.site.ru/script_([0-9]*).html http://www.site.ru/script.php?id=$1 Теперь при обращении к сайту www.site.ru/script_1.html произойдёт замена на http://www.site.ru/script.php?id=1, которая в последствии будет выполнена. “А в чём же здесь защита?” спросите вы. Обратите внимание на script_([0-9]*).html, здесь у нас идёт проверка переданных скрипту параметров, т.е. как мы видим: если передаваемый параметр будет содержать кроме числовых ещё какие-нибудь символы, то запрос выполнен не будет… Дополнительную информацию о mod_rewrite и о его использовании можно найти в документации по серверу Apache. www.apache.org Outro Ну вот, я кратко описал способы решения данной проблемы. Если вам есть что добавить, просьба отписать в эту тему. Всем удачи.
Достаточно прогонять текстовые переменные по даной функции и больше не чего не надо PHP: function secure_sql($value) { if( get_magic_quotes_gpc()) { $value = stripslashes( $value ); } if( function_exists( "mysql_real_escape_string" )) { $value = mysql_real_escape_string( $value ); } else { $value = addslashes( $value ); } return $value; }
На вид большая функция а =\\ 1) Зачем цифры переводить через эту функцию? Достаточно PHP: <?php $xek = intval($xek); ?> 2) Оох... где-то еще есть серваки с пхп 3 чтобы делать поверку на существование функции mysql_real_escape_string ? 3) mysql_real_escape_string не экранирует символы % и _ также как mysql_escape_string что будет багой например при %LIKE% ..... Поэтому достаточно написать свою функцию в 3 строки с реплейсом % и _ на \%, \_ ну и mysql_real_escape_string
в топике ничего не упомянуто об: 1. реферере 2. сессии 3. прочие "особые" моменты )) Практически никто этого не обрабатывает, если говорить про фул_паф_дискложен