SQL — Інєкції

22

Від автора: якщо у вас застосовується введення даних користувачем через веб-сторінку з подальшою їх вставкою в базу даних SQL, існує ймовірність, що у вас можуть виникнути проблеми з безпекою. Пов’язано це з таким явищем, як SQL ін’єкція. У цій главі ми розглянемо, як вирішити дану проблему, і захистити ваші скрипти і SQL скрипти на стороні сервера, наприклад, PERL Script.

Ін’єкція зазвичай здійснюється, коли ви запитуєте у користувача певні дані, наприклад ім’я, а замість цього він вводить інструкцію SQL, яка несанкціоновано виконується в базі даних. Надані користувачем дані завжди повинні оброблятися в базі даних лише після їх валідації; як правило, вона виконується шляхом зіставлення з шаблонами.

У наведеному нижче прикладі name можуть використовувати тільки алфавітно-цифрові символи плюс підкреслення і воно може мати довжину від 8 до 20 символів (при необхідності ви можете змінити ці правила).

if (preg_match(«/^\w{8,20}$/», $_GET[‘username’], $matches)) {
$result = mysql_query(«SELECT * FROM CUSTOMERS
WHERE name = $matches[0]»);
} else {
echo «user name not accepted»;
}

Давайте розглянемо наступний приклад:

// supposed input
$name = «Qadir’; DELETE FROM CUSTOMERS;»;
mysql_query(«SELECT * FROM CUSTOMSRS WHERE name='{$name}'»);

Передбачається, що виклик функції має отримати запис з таблиці CUSTOMERS, де стовпець name відповідає імені, вказаному користувачем. Зазвичай $name містить тільки алфавітно-цифрові символи і, можливо, прогалини. Але тут до $name додається абсолютно новий запит, який при виконанні викликає катастрофічні наслідки; DELETE-запит видаляє всі записи з таблиці CUSTOMERS.

На щастя, якщо ви використовуєте MySQL, функція mysql_query() не допускає стекування запитів або виконання декількох SQL-запитів в одному виклику функції. Якщо ви спробуєте виконати стек запитів, виклик завершиться помилкою.

Тим не менш, інші розширення бази даних PHP, такі як SQLite і PostgreSQL, приймають стекированые запити, виконуючи всі запити в одному рядку, що призводить до серйозних проблем з безпекою.

Запобігання SQL-ін’єкцій

Ви можете контролювати введення символів escape за допомогою скриптових мов, таких як PERL і PHP. Розширення MySQL PHP надає функцію mysql_real_escape_string(), яка запобігає введення символів, що мають в MySQL особливе значення.

if (get_magic_quotes_gpc()) {
$name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query(«SELECT * FROM CUSTOMERS WHERE name='{$name}'»);

Проблеми пов’язані з LIKE

Щоб не допускати проблем, пов’язаних з LIKE, користувальницький механізм екранування повинен перетворювати символи «%» і «_» в їх буквальні відповідності. Для цього використовується функція addcslashes(), яка дозволяє вказати діапазон символів для екранування.

$sub = addcslashes(mysql_real_escape_string(«%str»), «%_»);
// $sub == \%str\_
mysql_query(«SELECT * FROM messages
WHERE subject LIKE ‘{$sub}%'»);