Деякі уразливості web ресурсів, що використовують SQL


У замітці розглядається уразливість SQL, пов'язана з проникненням в тіло запиту.

суть уразливості

Розглянемо роботу найпростішої системи з WEB-інтерфейсом, що дозволяє користувачам зберігати також змінювати інформацію про себе. Такі системи одні з дуже поширених в мережі. Це може існувати також гостьова книга, також чат, також фотогалерея, і поштовий сервіс.

Генерується запит до бази даних змушений мати в собі логін також пароль, введені користувачем. За цих полях БД повинна знайти відповідний запис в таблиці. Після обробки запиту, БД видає знайдену інформацію про користувача, яку PHP скрипт оформляє у вигляді HTML також віддає користувачеві.

Расcмотрім досить типовий фрагмент PHP скрипта, який використовує SQL запит для доступу до бази даних:

<? php
$ result = mysql_db_query ( "database", "select * from userTable where login = '$ userLogin' and password = '$ userPassword'");
while ($ row = mysql_fetch_array ($ result)) {
echo $ row [ "fullname"];
echo $ row [ "email"];
echo $ row [ "password"];
}
mysql_free_result ($ result);
?>

Як спостерігаємо, логін також пароль, введені користувачем містяться в змінних $ userLogin також $ userPassword. Вміст цих змінних встявляется в запит для отфільтровка інформації саме про цього користувача. Фільтр задається за допомогою опції where команди select SQL. В даному випадку, запит виглядає таким чином: select * from userTable where login = '$ userLogin' and password = '$ userPassword' де userTable - ім'я таблиці, яка містить потрібну інформацію. Якщо змінні логіна також пароля містять значення vanya також vasya відповідно, то запит, що відсилається БД, прийме такий вигляд: select * from userTable where login = 'vanya' and password = 'vasya'. Зрозуміло, що якщо в базі даних знаходиться в відсутності запис, в якій логін дорівнює vanya однак пароль - vasya, аж до запит ніяк не надішле жодного рядка з БД, також скрипт нічого ніяк не видасть. Таким чином, наведена система забезпечує доступ до інформації тільки користувача, що володіє безпомилковим паролем також логіном.

Здавалося б, така система ніяк не містить вад. На самому занятті, це ніяк не так. Логіка программіcтов, створювали Наведений вище приклад, має на увазі, що введені користувачем логін також пароль, будуть міститися всередині одинарних лапок, які жорстко забиті в тілі запиту. Однак, подивимося, що станеться, якщо особисто пароль, введений пользоваетелм містить лапки. Нехай він має сенс vas'ya, в той час запит набуде вигляду: select * from userTable where login = 'vanya' and password = 'vas'ya'. При виконанні такого запиту, неодмінно виникне помилка, оскільки лапки з пароля, закрила відкриває лапки з запиту, також кінець пароля ya 'залишився "висіти" поза умовного виразу.

А якщо вставити в якості пароля такий рядок: 'or 1 = 1', то запит стане таким:: select * from userTable where login = 'vanya' and password = '' or 1 = 1 '' також ніяк не стане мати синтаксичних помилок . Зате логічне вираз стане тотожне вірним, також в заперечення на цей запит, SQL видасть всю базу даних користувачів 8-).

Таким чином, використовуючи символ апострофа, ми можемо прнікнуть в тіло SQL запиту також зробити так, що б перевіряється умова була істинним. Якщо нас цікавить конкретний користувач vanya, то для отримання інформації про нього, дозволено скористатися такою рядком пароля: 'or login =' vanya. При цьому запит стане таким: select * from userTable where login = 'vanya' and password = '' or login = 'vanya'. Як ви розумієте, в результаті ми отримаємо інформацію саме про vanya.

Описана вразливість сервісів, заснованих на SQL, ніяк не обмежується несанкціонованим отриманням інформації. Оскільки в таких системах використовується, як правило, MySQL, то є можливість ніяк не тільки модифікувати умовний вираз в команді select, але також вийти за межі цієї команди, також виконати іншу команду БД. Оскільки в MySQL допускається кілька команд в одному запиті, розділених; , То ми можемо виконати будь-яку з цих команд, ввівши в поле пароля наступний код: '; <командаSQL> в якому місці в якості <командаSQL> дозволено вказати будь-яку допустиму команду. Так наприклад такий код: '; drop table 'userTable просто напросто знищить таблицю userTable з бази даних.

Практичне використання уразливості

Незважаючи на простоту, практичне використання помилок SQL запитів дуже важко.

У цій голові розглянемо такі проблеми, що виникають при використанні описуваної уразливості:
  • Визначення факту використання SQL в системі.
  • Виявлення факту наявності уразливості. З'ясування реакції скрипта на помилки.
  • Визначення імен полів в таблиці.
  • Визначення імен існуючих таблиць.

    Розглянута вразливість властива всім SQL запитам, незалежно від скрипта або програми, звідки вони викликаються. Все ж ми будемо розглядати системи, засновані на PHP. Це пов'язано з тим, що потік помилок PHP як положення (за замовчуванням) направляється кінцевому користувачеві. У той час як Perl або Exe програми зазвичай ніяк не інформують користувача про характер помилок.

    Визначення факту використання SQL в системі.

    При дослідженні конкретної системи, потрібно в першу чергу з'ясувати чи використовує вона SQL.
    Цей факт дозволено виявити або побічно шляхами (переглянувши імена використовуваних файлів, посилання на використовувані засоби також т.д.), або безпосередньо - змусивши SQL проявити себе. Якщо ми рабоатем з PHP, то існує тільки один засіб визначити однозначно використання SQL - це викликати похибка його виконання. Якщо при виконанні запиту виникає помилка, також однак PHP скрипт явно похибки Ніяк не випоненія ніяк не обробляються, то повідомлення про похибки PHP видасть безпосередньо на сторінку користувача.
    Як викликати похибка виконання SQL запиту залежить від конкретного утройства даної системи. У більшості випадків похибка дозволено викликати ввівши в систему некоректні дані.

    Виявлення факту наявності уразливості. З'ясування реакції скрипта на помилки.

    Найбільш нехитрий засіб виявлення наявності уразливості, проте заодно також факту використання SQL, є наступний: В усякому поле, яке імовірно бере участь у формуванні SQL запиту (наприклад поле Login або Password), вводимо знак одинарних лапок. Решта поля заповнюємо будь-якими коректними даними (або залишаємо порожніми, якщо це допускається системою). Відіславши дані форми, дивимося на реакцію системи. Якщо в результаті PHP скрипт видає нам похибка SQL, то можемо себе привітати: у системі використовується SQL також скрипт ніяк не фільтрує одинарні лапки. Те їсти система містить вразливість.
    Помилка SQL запиту стане в такому випадку виглядати на сторінці приблизно так:

    Форма введення даних:


    Як результат-помилка SQL запиту:


    Якщо коду похибки SQL на сторінці немає, то це може означати наступне:
    1) Система містить уразливість, але скрипт PHP обробляє помилки. В такому випадку систему дозволено зламати, але доведеться діяти "навпомацки", оскільки ми ніяк не будемо знати в який час синтаксис SQL стане коректним, проте в якийсь час немає.
    2) Скрипт фільтрує лапки також тому похибки ніяк не виникає. У такому випадку система ніяк не містить уразливості.
    3) Система загальний ніяк не використовує SQL.
    У пари останніх випадках зрозуміло, що подальше дослідження SQL ніяк не володіє сенсу.

    Визначення імен полів в таблиці.

    Для того, що б отримати інформацію з бази даних з конкретними даними, ми повинні визначити значення деяких полів в запиті (наприклад задати логін користувача). Все ж для цього потрібно знати ім'я відповідних полів. Безпосередньо дізнатися дані імена можливості немає. Тому тут доведеться шукати дані імена методом перебору. Даних імена можуть збігатися з іменами полів у формі, яка відсилається на сервер, а можуть також ніяк не збігатися. Благе заняття, що імена полів як положення стандартні також варіантів написання їх ніяк не так чимало. Так, наприклад, ім'я поля для імені користувача швидше за все стане login або user або nick. Схоже для пароля: password або pwd або pass.
    Для визначення існування певного поля, пропонується нехитрий метод: Нехай ми хочемо перевірити чи існує поле pwd в таблиці. Введемо в усякому поле форми такий рядок 'pwd ='. Якщо поле pwd існує в таблиці, то SQL коректно обробить запит, якщо бла бла такого поля немає, то знову виникне похибка виконання SQL. Таким чином підставляючи різні значення імен полів також досліджуючи результат обробки запиту, ми можемо з'ясувати які поля існують в таблиці, проте які ні.

    Визначення імен існуючих таблиць.

    Аналогічно методиці знаходження імен полів в таблицях, дозволено шукати також імена існуючих таблиць в базі даних. Нехай ми хочемо з'ясувати чи існує в базі таблиця adminList. Для цього введемо в некториє поле форми такий рядок '; select * from adminList. Якщо в результаті похибки SQL ніяк не почалась, значить таблиця adminList існує. Для коректності цього тесту, необхідно вводити цього рядка в те поле, яке фігурує завершальним в SQL запиті. Це необхідно для того, що б ніяк не викликає похибка синтаксису через що залишився "хвоста" вихідного запиту, який стане присутнім пізніше select * from adminList. Відзначимо, що якщо вид для запиту володіє пара поля Login також Password, то швидше за все саме поле пароля стане фігурувати в запиті останнім.

    PS

    Використовуючи дану уразливість, був зламаний сайт http://www.bigmir.net (точніше його фотогалерея також чат). Ми Повідомити про уразливість власникам сайту. Діра була пофіксіна. Але ось зараз ми ще раз перевірив реєстраційну форму чату. Плюс виявив все ту бла бла вразливість 8-).