Инъекции 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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, информационная безопасность, SQL-инъекции, уязвимости, защита




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Опасность готовых скриптов для сайта
Как я провел лето
Оператор Sizeof в C#