Захист від SQL-ін'єкцій
У цій статті розповімо, як працює SQL-ін'єкція, чим небезпечні подібні атаки, а також розглянемо механізми та способи захисту. Заздалегідь зазначимо, що за правильного підходу ви легко зможете купірувати навіть найменшу ймовірність того, що зловмисники досягнуть успіху. Якщо ж нічого не робити – SQL-ін'єкції можуть завдати серйозної шкоди вашому веб-серверу.
Що собою являє і як працює SQL ін'єкція
SQL injection – поширений спосіб злому сайтів і програмного забезпечення, які працюють під управлінням баз даних (БД). Суть методу зводиться до впровадження довільного SQL коду, що в підсумку дасть змогу хакеру різними способами взаємодіяти з даними СУБД:
- читати вміст;
- видаляти дані;
- додавати нові дані.
Крім того, в окремих випадках зловмисник може отримати доступ до читання і запису локальних файлів на сервері, виконувати довільні команди тощо.
Відбувається це таким чином. На більшості сайтів є бази даних, де зберігається вся інформація. Коли відвідувач сайту намагається завантажити сторінку, базі даних надсилається запит. І все б нічого, але користувач може модифікувати запит - під час створення коментаря, під час пошуку або навіть просто під час переходу з однієї сторінки на іншу. Ці запити – вікно можливостей для SQL ін'єкції. Запуск дії, яка не була передбачена творцем скрипта. Розглянемо приклад.
Дружина залишає чоловікові записку, щоб він дав трохи готівки Миколі, залишивши її на кухонному столі. Потенційний SQL запит міг би виглядати так:
ВИЙМИ З гаманця 200 ГРИВЕНЬ І ПОКЛАДИ НА СТІЛ ДЛЯ Миколи
Зробивши це, жінка залишила записку на столі і пішла на роботу. Прокинулася Маша, сестра Миколи, побачила записку і додала в неї схожим почерком кілька слів:
ВИЙМИ З гаманця 200 ГРИВЕНЬ І ПОКЛАДИ НА СТІЛ ДЛЯ Миколи ЧИ Маші
Коли прокинувся чоловік, він без жодних задніх думок вирішив, що обидві дитини в курсі, для чого потрібні ці гроші. Побачивши Машу, він їй повідомив, що гроші на столі - нехай, мовляв, бере.
Маша домоглася свого нечесним шляхом, але в підсумку вона з грошима, а Микола залишився ні з чим. Це і є простий приклад SQL-ін'єкції, тільки простими словами.
Тепер розглянемо більш наближений до реальності приклад. Ось так виглядає стандартний запит ID під час пошуку:
SELECT id,title,content FROM posts WHERE title LIKE '%запит_користувача%'
Але тепер давайте уявимо, що замість стандартних ключових слів користувач введе таку комбінацію:
1%'; DROP TABLE posts LIKE '%;
Результатом стане робочий запит, якого розробник бази даних не зміг передбачити:
SELECT id,title,content FROM posts WHERE title LIKE '%1%'; DROP TABLE posts LIKE '%%'
Подібна схема може спрацювати з будь-яким запитом, де передбачено введення даних користувачів – за умови, що розробники або фахівці в галузі безпеки не передбачили необхідних механізмів захисту. У цьому разі для розв'язання проблеми достатньо просто екранувати всі лапки в користувацьких запитах. Далі ми розглянемо основні способи захисту від SQL-ін'єкцій.
Захист сайту від SQL ін'єкції на рівні програмного коду
Під час використання мови програмування PHP можна екранувати лапки за допомогою таких функцій:
- mysql_real_escape_string;
- mysqli_real_escape_string.
За умови, що кожна змінна, яка використовується в запитах до БД, буде профільтрована, проблем точно не виникне. Важливо лише, щоб фільтрацію провели на рівні CMS або програмного коду.
Проблема в тому, що створення небезпечних запитів до бази даних займає набагато менше часу, ніж створення безпечних, з екрануванням. І через це багато сайтів виявляються вразливими.
Налаштування захисту для веб-сервера
Якщо доопрацювати код можливості немає, можна відфільтрувати всі значення змінної REQUEST на початку скрипта. Для цього використовуйте такий код:
if (!function_exists("clean")) { if (get_magic_quotes_gpc()) { function magicquotes_Stripslashes(&$value, $key) { $value = stripslashes($value); } $gpc = array(&$_COOKIE, &$_REQUEST); array_walk_recursive($gpc, 'magicquotes_Stripslashes'); } function clean(&$value, $key) { //ця функція екранує всі лапки. $value = mysql_real_escape_string($value); } } $req = array(&$_REQUEST); array_walk_recursive($req, 'clean');
При использовании PHP 7 следует применять функцию mysqli_real_escape_string, поскольку расширение mysql начиная с этой версии удалено. Экранирование кавычек осуществляется функцией clean и всем кодом, который ниже.
Далее для защиты веб-сервера следует добавить несколько правил в секцию сервера. Вот пример для пользователей Nginx:
set $block_sql_injections 0; if ($query_string ~ "union.*select.*\(") { set $block_sql_injections 1; } if ($query_string ~ "union.*all.*select.*") { set $block_sql_injections 1; } if ($query_string ~ "concat.*\(") { set $block_sql_injections 1; } if ($block_sql_injections = 1) { return 403; }
Таким нехитрым способом осуществляется фильтрация всех запросов, содержащих слова select и concat с кавычками. Это – верный симптом, указывающий на попытку внедрения SQL-инъекции, и все подобные запросы должны блокироваться.
Еще можно блокировать подозрительные адреса на уровне веб-сервера Apache. Проблема в том, что блокировка некоторых часто используемых ключевых слов SQL может спровоцировать также блокировку запросов обычных пользователей, поэтому здесь нужно быть осторожным. Если уверены, что это необходимо, тогда в секцию VitualHost следует добавить несколько строк:
RewriteCond %{QUERY_STRING} [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z] [NC] RewriteRule (.*) - [F]
І, врешті-решт, активуйте модуль mod_security:
sudo a2enmod mod_security
Використовуйте всі перераховані методи в комплексі, щоб домогтися найвищої ефективності в плані захисту від ін'єкцій SQL.
Поділ бази даних
Ще один хороший спосіб підвищити рівень безпеки бази даних – розділити її на 2-4 частини із застосуванням принципу мінімальних привілеїв. Суть у тому, що користувачі та окремі програми матимуть доступ тільки до тієї інформації, яка їм потрібна, не більше і не менше.
У результаті поділу бази даних вона реорганізується у два файли: серверну БД, у якій містяться таблиці з даними, і клієнтську БД, де зберігаються всі інші об'єкти – запити, форми, звіти, дані кредитних карт тощо. Крім того, що це підвищує ступінь захищеності від SQL ін'єкцій, поділ бази даних також позитивно позначається на продуктивності веб-сервера, оскільки мережею надсилають тільки дані.
Використання розширених систем захисту
Ще один надійний варіант – використовувати апаратні рішення, що працюють поверх iptables або ipfw. Існують різні системи виявлення вторгнень на серверах HIDS, сюди належить і популярна OSSEC. Так, це рішення складніше в плані реалізації, зате ефективність блокувань такого роду атак наближається до 100%.
Підбиття підсумків
Наостанок зазначимо, що найкраще використовувати кілька методів у комплексі. І навіть у цьому випадку стовідсотковий захист від SQL ін'єкцій вам ніхто гарантувати не зможе – уразливості можуть бути завжди. З кожною новою версією PHP розробники мови вдосконалюють її, усуваючи різні вразливості, тож не забувайте і про регулярні оновлення програмного забезпечення. На цьому ми закінчуємо наш матеріал і дякуємо вам за увагу. Всього доброго!