SQL-ін'єкція
SQL ін'єкція — один з поширених способів злому сайтів та програм, що працюють з базами даних, заснований на впровадженні в запит довільного SQL-коду.
Впровадження SQL, залежно від типу СКБД та умов впровадження, може дати можливість атакуючому виконати довільний запит до бази даних (наприклад, прочитати вміст будь-яких таблиць, видалити, змінити або додати дані), отримати можливість читання та/або запису локальних файлів та виконання довільних команд на сервері.
Атака типу впровадження SQL може бути можлива за некоректної обробки вхідних даних, що використовуються в SQL-запитах.
Розробник застосунків, що працюють з базами даних, повинен знати про таку уразливість і вживати заходів протидії впровадженню SQL.
Принцип атаки
Припустимо, серверне ПЗ, отримавши вхідний параметр id, використовує його для створення SQL-запиту. Розглянемо такий PHP-скрипт:
...
$id = $_REQUEST['id'];
$res = mysql_query("SELECT * FROM news WHERE id_news = $id");
...
Якщо на сервер переданий параметр id, що дорівнює 5 (наприклад так: http://example.org/script.php?id=5), то виконається такий SQL-запит:
SELECT * FROM news WHERE id_news = 5
Але якщо зловмисник передасть як параметр id рядок -1 OR 1=1 (наприклад, так: http://example.org/script.php?id=-1+OR+1=1), то виконається запит:
SELECT * FROM news WHERE id_news =-1 OR 1=1
Таким чином, зміна вхідних параметрів шляхом додавання в них конструкцій мови SQL викликає зміну в логіці виконання SQL-запиту (в цьому прикладі замість новини із заданим ідентифікатором будуть вибрані всі наявні в базі новини, оскільки вираз 1=1 завжди істинний).
Впровадження в рядкові параметри
Припустимо, серверне ПЗ, отримавши запит на пошук даних у новинах параметр search_text, використовує його в наступному SQL-запиті (тут параметри екрануються лапками) :
...
$search_text = $_REQUEST['search_text'];
$res = mysql_query("SELECT id_news, news_date, news_caption, news_text, news_id_author
FROM news WHERE news_caption LIKE('%$search_text%') ");
Зробивши запит виду http://example.org/script.php?search_text=Test ми отримаємо виконання такого SQL-запиту:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%Test%')
Але, запровадивши в параметр search_text символ лапки (який використовується в запиті), ми можемо кардинально змінити поведінку SQL-запиту. Наприклад, передавши як параметр search_text значення ') +and+ (news_id_author='1, ми змусимо виконати запит:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%') and (news_id_author='1%')
Використання UNION
Мова SQL дозволяє об'єднувати результати декількох запитів за допомогою оператора UNION. Це надає зловмисникові можливість отримати несанкціонований доступ до даних.
Розглянемо скрипт відображення новини (ідентифікатор новини, яку необхідно відобразити, передається в параметрі id) :
$res = mysql_query("SELECT id_news, header, body, author FROM news WHERE id_news = ". $_REQUEST['id']);
Якщо зловмисник передасть як параметр id конструкцію -1 UNION SELECT 1,username, password,1 FROM admin, це викличе виконання SQL-запиту
SELECT id_news, header, body, author FROM news WHERE id_news =-1 UNION SELECT 1,username,password,1 FROM admin
Оскільки новини з ідентифікатором -1 завідомо не існує, з таблиці news не буде вибрано жодного запису, проте в результат потраплять записи, несанкціоновано відібрані з таблиці admin внаслідок ін'єкції SQL.
Використання UNION + group_concat()
У деяких випадках хакер може провести атаку, але не може бачити більше однієї колонки. У разі MySQL зломщик може скористатися функцією:
group_concat(col, symbol, col)
яка об'єднує кілька колонок в одну. Наприклад, для прикладу цього вище виклик функції буде таким:
-1 UNION SELECT group_concat(username, 0x3a, password) FROM admin