Способы защиты от SQL-инъекций (Rating: +4)
Самый простой способ защиты от SQL-инъекции – «обрамлять» параметры SQL-запроса одиночными кавычками ('), поскольку через GET- и POST-запрос невозможно передать символ одиночной кавычки (он будет автоматически заменен сочетанием символов – \' – т.е. экранироваться).
Однако такой способ не гарантирует стопроцентной защиты от SQL-инъекций. Приведем несколько дополнительных способов
Всегда проверяйте числовые параметры функцией intval. При проверке такого параметра:
10' union select 1,2,3/*
, функция intval вернет значение 10, что исключает возможность SQL-инъекции. Однако не все параметры являются числовыми. Например:
http://somesite.dom/index.php?section=about
Здесь параметр section является строковым, и функция intval здесь не может быть применена. Что бы избежать вредоносного запроса, можно воспользоваться следующими функциями:
mysql_escape_string – экранирует все спецсимволы;
Так же можно проверять строковые параметры на наличие в них таких слов как "select", "union", "order", "char", "where", "from".
Пример функции на PHP 5:
Для обеспечения конфиденциальности логина и пароля для доступа к базе данных, функции подключения к базе данных лучше хранить в отдельном файле и подключать его в каждой странице сайта.
Так же, отключение вывода на экран ошибок, возникших при неверном запросе, сильно усложняет задачу злоумышленнику. Что бы отключить вывод ошибок достаточно написать следующее (например, в файле подключения базы данных):
ini_set('display_errors', '0');
Старайтесь проверять результат каждого выполняемого запроса на выполнение и количество найденных записей. Если их количество равно нулю, перенаправляйте пользователя, например, на главную страницу, это обеспечит хорошую защиту от SQL-инъекций.
Пример на PHP 5:
Все описанные выше способы не гарантируют стопроцентной защиты от SQL-инъекций, однако, помогут предотвратить их в подавляющем большинстве случаев.
Added: ZipeR
05.01.2011 / 07:30SELECT * FROM `table_name` WHERE `param` = '$param_name' ORDER BY `sort` ASC; SQL-запрос в случае инъекции будет выглядеть примерно так: SELECT * FROM `table_name` WHERE `param` = '10 union select 1,2,3 /*' ORDER BY `sort` ASC; Т.е. для обработчика запросов, при отбрасывании части запроса после /*, запрос будет выглядеть примерно так: SELECT * FROM `table_name` WHERE `param` = '10 union select 1,2,3 Обработчик запросов, не найдя закрывающей кавычки посчитает этот запрос ошибочным и не выполнит его. Если попытаться GET-запросом передать фрагмент кода с кавычкой: 10' union select 1,2,3/* , то, после отбрасывания комментария, SQL-запрос будет выглядеть так: SELECT * FROM `table_name` WHERE `param` = '10\' union select 1,2,3В этом случае обработчик также не выполнит этот запрос, потому что не найдет закрывающей кавычки, т.к. сочетание символов \' будет расценено не как закрывающая кавычка, а как внутренний символ ', который должен содержаться в поле `param`.
Однако такой способ не гарантирует стопроцентной защиты от SQL-инъекций. Приведем несколько дополнительных способов
Всегда проверяйте числовые параметры функцией intval. При проверке такого параметра:
10' union select 1,2,3/*
, функция intval вернет значение 10, что исключает возможность SQL-инъекции. Однако не все параметры являются числовыми. Например:
http://somesite.dom/index.php?section=about
Здесь параметр section является строковым, и функция intval здесь не может быть применена. Что бы избежать вредоносного запроса, можно воспользоваться следующими функциями:
mysql_escape_string – экранирует все спецсимволы;
Так же можно проверять строковые параметры на наличие в них таких слов как "select", "union", "order", "char", "where", "from".
Пример функции на PHP 5:
function escape_inj ($text) { $text = strtolower($text); // Приравниваем текст параметра к нижнему регистру if ( !strpos($text, "select") && // !strpos($text, "union") && // !strpos($text, "select") && // !strpos($text, "order") && // Ищем вхождение слов в параметре !strpos($text, "where") && // !strpos($text, "char") && // !strpos($text, "from") // ) { return true; // Вхождений нету - возвращаем true } else { return false; // Вхождения есть - возвращаем false } } $section = $_GET[section]; // Читаем параметр if (!escape_inj ($section)) { // Проверяем параметр echo "Это SQL-инъекция."; exit (); } else { $result = mysql_query ("SELECT * FROM `tbl_name` WHERE `section` = $section "); ... // Продолжаем работу }Никогда не храните пароли в базе данных в открытом виде, обязательно шифруйте их (например, функцией sha1). С помощью SQL-инъекции легко "достать" данные из базы данных, а если они будут зашифрованы, то есть большая вероятность того, что злоумышленник не сможет ими воспользоваться.
Для обеспечения конфиденциальности логина и пароля для доступа к базе данных, функции подключения к базе данных лучше хранить в отдельном файле и подключать его в каждой странице сайта.
Так же, отключение вывода на экран ошибок, возникших при неверном запросе, сильно усложняет задачу злоумышленнику. Что бы отключить вывод ошибок достаточно написать следующее (например, в файле подключения базы данных):
ini_set('display_errors', '0');
Старайтесь проверять результат каждого выполняемого запроса на выполнение и количество найденных записей. Если их количество равно нулю, перенаправляйте пользователя, например, на главную страницу, это обеспечит хорошую защиту от SQL-инъекций.
Пример на PHP 5:
$section = $_GET[section]; // Читаем параметр $result = mysql_query ("SELECT * FROM `tbl_name` WHERE `section` = $section "); // выполняем запрос if (!$result || mysql_num_rows ($result) == 0) { // Кол-во найденных полей = 0, или запрос не был выполнен header ("Location: http://$_SERVER[HTTP_HOST]/"); // Уходим на главную страницу exit (); } else { ... // Продолжаем работу }Если Ваш сайт не содержит разделов, в которых производится запись или редактирование строк в базе данных, то необходимо у пользователя базы данных, под которым происходит соединение с базой, отключить все права, кроме права на чтение данных. По-умолчанию, у пользователя базы данных есть права и на удаление, и на редактирование. Для разделов сайта, требующих больших прав, например книга отзывов или форум стоит завести отдельного пользователя, у которого будет право на редактирование только конкретной таблицы. А для системы управления сайтом необходимо завести отдельного пользователя базы данных, т.к. ему необходимы полные права.
Все описанные выше способы не гарантируют стопроцентной защиты от SQL-инъекций, однако, помогут предотвратить их в подавляющем большинстве случаев.
Rating:
+4
Views: 1791Comments (0) »