Инъекции SQL: основы защиты
В этой небольшой заметке я попробую показать вам, как можно защититься от самых простых SQL-инъекций. Это будет первая из цикла, посвященных уязвимостям и безопасности. Кстати, мой блог тоже время от времени пытаются взломать с помощью инъекций. Если будет время, то сделаю обзор используемых хакерами способов для этого.
Никогда не доверяйте данные, которые водит пользователь или передает вам в качестве параметров на сайт! Первое правило любого веб-разработчика: никогда не доверяйте пользовательскому вводу. Инъекции может произойти, когда ввод пользователя будет трактоваться и использоваться для создания новых данных.
Ваш испытательный срок в качестве PHP разработчика может немедленно завершиться, если вы в своем коде используете такие конструкции:
mysqli_query( $link, "SELECT hero, rating FROM books WHERE name = '" . $_GET['book_name'] . "'" );
mysql> SELECT hero, rating FROM books WHERE name = ' Self-made Sauerkraut' UNION ALL SELECT user, password FROM mysql.user WHERE '' = ''; +--------+--------+ | hero | rating | +--------+--------+ | Ааз | 10 | | root | | +--------+--------+ 2 rows in set (0,01 sec)Не надо быть супер хакером, чтобы использовать для взлома сайта такой код. Воспользовавшись любым поисковиком, вы немедленно найдете кучу инструментов, которые помогут вам осуществить SQL-инъекции на такой веб-сайт. Эти инструменты не являются злом. Они помогут вам лучше разбираться в вопросах безопасности. Чтобы сохранить свою работу, вам необходимо познакомиться с ними.
mysqli_query( $link, "SELECT hero, rating FROM books WHERE name = '" . mysqli_real_escape_string($_GET['book_name']) . "'" );
mysql> SELECT hero, rating FROM books WHERE name = ' Self-made Sauerkraut\' UNION ALL SELECT user, password FROM mysql.user WHERE \'\' = \''; Empty set (0,00 sec)Экранируем
Вышеуказанные атаки становится гораздо сложнее, когда используется экранирование входных значений прежде, чем составлять динамически SQL-запрос из входных данных.
Отказываем в обслуживании
Однако, это не панацея. Инъекция все еще возможна, если на вход принимается числовая константа в SQL.
mysqli_query( $link, "SELECT name, rating FROM books WHERE rating > " . mysqli_real_escape_string($_GET['rating']) );
mysql> SELECT name, rating FROM books WHERE rating > 3 AND 0 = IF(1, BENCHMARK(1000000, MD5(REPEAT(CONVERT(1, CHAR), 1000))), 0); +----------------------+--------+ | name | rating | +----------------------+--------+ | Мифо-толкования | 10 | | Мифо-указания | 8 | +----------------------+--------+ 2 rows in set (18,38 sec)Фильтруем
Один из способов обезопасить ваш сайт является фильтрация. PHP 5.2 и более поздние версии поставляются с удобным набором встроенных фильтров и проверки функций. Используйте их.
$rating = filter_var($_GET['rating'], FILTER_VALIDATE_INT); if (false === $rating) { die("Вы мне морочите голову?"); } $options = array( 'options' => array( 'min_range' => 0, 'max_range' => 100, 'default' => 5, )); $rating = filter_var($_GET['rating'], FILTER_VALIDATE_INT, $options); if (false === $rating) { die("Вы мне морочите голову?"); }Это только вершина айсберга
Помните, что даже использование PDO не дает гарантии защищенности от SQL-инъекций, даже применение NoSQL совсем не означает, что инъекция как таковая совершенно невозможна. Постоянно повышайте свою компьютерную грамотность, читайте и узнавайте о новых уязвимостях.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.