SQL-ін’єкція
Original on http://shiflett.org/articles/sql-injection
Ласкаво просимо в черговий випуск безпеки Corner. Тема цього місяця є SQL ін’єкції, атаки, що часто відвідує уми розробників PHP, але для яких не вистачає гарної документації.
Більшість веб-додатки взаємодіють з базою даних, і дані, що зберігаються в ньому часто відбувається з віддалених джерел. Таким чином, при створенні заяві SQL, ви часто використовуєте внесок у його будівництво. Типові ін’єкції SQL атаки подвиги цього сценарію, намагаючись відправити фрагментів дійсних SQL запитів у вигляді несподіваного значення GET і POST даних. Ось чому уразливості SQL ін’єкції часто вини поганої фільтрації та екранування, і цей факт не може бути підкреслено достатньо.
Ця стаття пояснює, ін’єкції SQL, дивлячись на кілька атак приклад, а потім введення деяких простих і ефективних гарантій. Застосовуючи передовій практиці, ви можете практично повністю усувають SQL ін’єкція зі списку безпеки.
SQL-ін’єкція
На мить поставити себе в ролі нападника. Ваша мета спочатку просто. Ви хочете отримати який-небудь несподівану заяву SQL виконується в базі даних. Ви тільки хочете отримати щось на роботу, бо це покаже те, що програма має потенційну вразливість. У вас є стільки ж шансів, скільки хочете, і у вас є багато інформації для роботи. Наприклад, розглянемо просту форму аутентифікації показано на малюнку 1.
Малюнок 1:

Для того, щоб отримати більш докладну інформацію про цю форму можна переглядати джерело:
<form action="/login.php" method="POST"><p>Username: <input type="text" name="username" /></p><p>Password: <input type="text" name="password" /></p><p><input type="submit" value="Log In" /></p></form>
Ви вже можете зробити дуже обгрунтоване припущення про тип SQL твердження, що цей додаток може використовувати для перевірки облікові дані для доступу. Це, швидше за все,SELECTзаяві. Ви можете також зробити припущення про іменуванні використовуються в таблиці бази даних, тому що він, ймовірно, відповідає прості імена, використовувані в HTML формі. (Це також можливо, що ви можете викликати помилку, яка розкриває цю інформацію для вас.) Тому що ця форма призначена для аутентифікації, мабуть, немаєWHERE пункт, який використовує $_POST['username'] і $_POST['password'].
З усього цього, ви можете передбачити наступне:
<?php$sql = "SELECT count(*)FROM usersWHERE username = '{$_POST['username']}'AND password = '...'";>?>
Припускаючи, що це припущення вірне, то, що можна зробити, щоб маніпулювати цим запитом? Уявіть собі, відправка наступні ім’я користувача:
chris' /*
Заява SQL стає наступним:
SELECT count(*)FROM usersWHERE username = 'chris' /*'AND password = '...'";
У цьому прикладі, /*використовується для початку багаторядковий коментар, ефективно припинення запиту в цій точці. Це була успішно протестована з MySQL. Стандартний коментар в SQL починається з--, І це тривіальний, щоб спробувати та інше.
Цей запит передбачає успішну спробу аутентифікації тих пір, поки chrisобліковий запис існує, незалежно від пароля. Дана атака часто використовується для крадіжки облікових записів. Звичайно, будь-яке ім’я користувача може бути використаний (adminє популярним об’єктом). Таким чином, відправивши неправильно ім’я користувача, ви можете керувати, щоб увійти в без дійсної облікового запису.
Майте на увазі, що творчість відіграє велику роль у більшості атак. У попередньому прикладі, атака обмежена тип запиту (SELECT) І в тому, як ім’я користувача і пароль використовуються. Іншими словами, як нападника, ви кілька пов’язані, і ваші атаки повинні спробувати використати ситуацію в цих рамках. Інші типи запитів, відкривають нові можливості, і кращі звичаї, згадані в цій статті, застосовуються до всіх нападів SQL ін’єкції.
ДЕ Злом
WHEREпункт використовується для обмеження записів, які особливо матчів запиту. ДляSELECTзаяву, воно визначає записи, які не повертаються. ДляUPDATEзаяву, воно визначає записи, які були змінені. ДляDELETEзаяву, воно визначає записи, які будуть видалені. Якщо користувач може маніпулюватиWHERE пункту, Є багато можливостей, щоб зробити кардинальні зміни – вибір, оновлення та видалення довільних записів в базі даних.
Уявіть собі, SELECT Заява призначено для вилучення всіх номерів кредитних карт для поточного користувача:
<?php$sql = "SELECT card_num, card_name, card_expiryFROM credit_cardsWHERE username = '{$_GET['username']}'";?>
У даному конкретному випадку, додаток не може навіть запитувати ім’я користувача, але замість того, щоб надати його на заслання:
<a href="/account.php?username=shiflett">Credit Card Information</a>
Якщо користувач може мати кілька карт, додаток може циклу за результатами запиту до бази даних, що відображає номер карти, ім’я власника картки і термін її дії для кожної карти.
Уявіть собі користувача, який відвідує наступний ресурс:
/account.php?username=shiflett%27+OR+username+%3D+%27lerdorf
Це являє таке значення для ім’я користувача:
shiflett' OR username = 'lerdorf
При використанні в попередній запит SQL, $sql має таке значення:
SELECT card_num, card_name, card_expiryFROM credit_cardsWHERE username = 'shiflett' OR username = 'lerdorf'
Тепер користувач бачить список всіх кредитних карт, які належать або shiflett або lerdorf. Це досить великий уразливості. Звичайно, велику вразливість існує в даному конкретному прикладі, тому що користувач може довільно пройти будь-яке ім’я користувача в URL-адресі. Крім того, ім’я користувача, яке викликаєWHERE положення, щоб відповідати всі записи потенційно може розкрити всі рекорди:
shiflett' OR username = username
Уявіть собі, якщо даний ім’я користувача зберігається в базі даних (за допомогою окремої ін’єкції SQL, атаки), а власне ім’я користувача зловмисника. Кожен запит, який обмеженийWHEREположення для того, щоб застосовуватися тільки власний рекорд користувача можуть потенційно застосовуватися до всіх документів, а не. Це не тільки вкрай небезпечно, але це також робить подальші атаки дуже зручно.
Вхідна фільтрація
У даній статті передбачається magic_quotes_gpcвідключений. Якщо вона включена, ви можете вимкнути його або використовуватиfix_magic_quotes()Функція для ремонту введення.
Існують рекомендації, які ви повинні слідувати, щоб запобігти SQL-ін’єкцій, і вони пропонують дуже високий рівень захисту. Найбільш важливим кроком є фільтрація всіх вхідних (дані, що надходять від віддаленого джерела). Це включає в себе$_GET, $_POST, $_COOKIEІ т.д. Щоб прояснити це, розглянемо наступну HTML-форму:
<form action="/receive.php" method="POST"><select name="color"><option value="red">red</option><option value="green">green</option><option value="blue">blue</option></select><input type="submit"></form>
Зрозуміло, що очікувані значення є red, green, А blue. Таким чином, фільтрації вхідних даних повинні переконатися в цьому:
<?php$clean = array();switch ($_POST['color']) {case 'red':case 'green':case 'blue':$clean['color'] = $_POST['color'];break;default:/* Error */break;}?>
Цей код використовує окремий масив ($clean) Для збереження відфільтрованих даних. Це гарна ідея, щоб вибрати іменування, які допоможуть вам визначити потенційно зіпсований даних. У цьому прикладі,$clean['color'] можна довіряти, щоб утримувати коректний колір, тому що вона першою ініціалізації, а потім призначається тільки значення $_POST['color'] якщо це значення проходить тест.
Два найважливіших моментів для фільтрації вхідних даних є:
- Тільки приймати правильні дані, а не намагатися запобігти невірні дані.
- Виберіть іменування, яка допоможе вам розрізняти зіпсований дані з відфільтрованих даних.
Екранування виведення
З належним чином фільтрується вхід, ви вже досить добре захищена від шкідливих атак. Єдиний крок, щоб уникнути його так, що формат введення не випадково заважати формат заяви SQL. Якщо ви використовуєте MySQL, це просто вимагає передачі всіх даних черезmysql_real_escape_string() перед використанням:
<?php$mysql = array();$mysql['color'] = mysql_real_escape_string($clean['color']);$sql = "SELECT usernameFROM usersWHERE favorite_color = '{$mysql['color']}'";?>
У цьому випадку, припускаючи $clean['color']створений в попередньому прикладі, ви можете бути впевнені, що колір містить тільки алфавітних символів. (Це одна зred, green, Або blue.) Таким чином, екранування може бути зайвим, і це. Тим не менш, він як і раніше хороша звичка завжди екранувати дані. Ця практика допоможе вам не забути цей важливий крок, і він дотримується принципу захисту в глибину, в якому підкреслюється важливість надлишкові гарантії.
До наступної зустрічі…
Запобігання SQL ін’єкції легко, але це один з найбільш поширених вразливостей веб-додатків. Сподіваюся, ви тепер завжди буде дотримуватися наступних принципів:
- Вхідний фільтр.
- Втеча вихід.
NYPHP має корисний ресурс, який пояснює SQL втечі.
Сподіваюся, тепер ви можете надійно захистити ваші програми від атак SQL ін’єкції. До наступного місяця, в безпеці.
