Так звані "ін'єкції SQL" - це тип атаки на додаток, який використовує недоліки безпеки в базі даних. У цьому уроці ми побачимо приклади ін’єкцій SQL. Цей урок заснований на статті Стіва Фрідла, прикладеному на прикладі SQL Injection Attacks, який я рекомендую прочитати, або на шпаргалці з ін’єкцією SQL. Звичайно, метою цього уроку є підвищення обізнаності про необхідність захистити будь-який веб-додаток від такого типу атак.

Зразок заявки

Ми використаємо як приклад додаток, подібний до того, що описаний у вправах Бази даних 1.

  • Ця програма має меню з трьома опціями:
    • Стерти все, видалити та створити таблицю користувача, яка містить лише два поля (ім'я та пароль користувача).
    • Додайте користувачів, щоб додати імена користувачів та їх паролі до таблиці користувачів.
    • Введіть в систему, який імітує сторінку входу у веб-програмі, запитуючи ім’я користувача та пароль, перевіряючи, чи є вона в таблиці користувачів, та відповідаючи
      • ім'я користувача та пароль правильні.
      • ім'я користувача правильне, але пароль неправильний.
      • ім'я користувача неправильне.
  • Ця програма вразлива до деяких атак SQL-ін'єкцій, оскільки дані, що надсилаються користувачем, включаються до запитів до бази даних без попередньої обробки.
  • Ця програма не є вразливою до всіх атак введення SQL, про які йшлося в цьому уроці, оскільки вона використовує розширення PDO. Якщо ви хочете протестувати подібний додаток, вразливий до всіх атак, про які йдеться в цьому уроці, на своєму комп’ютері, ви можете завантажити цей файл (injection_sql_2.zip) і протестувати його на своєму комп’ютері.

SQL Injection 1 - отримуйте доступ до програми, не маючи імені користувача чи пароля

Коли користувач вводить ім’я користувача та пароль, програма відповідає на одне з трьох повідомлень:

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Правильне ім’я користувача та пароль.

Неправильне ім’я користувача.

Щоб перевірити, чи додаток включає дані, надіслані користувачем без попереднього лікування, ми можемо надіслати пропозицію (одинарну або подвійну) як дані.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Неправильне ім’я користувача.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Помилка запиту.

Це останнє повідомлення ("Помилка в запиті") повідомляє нам, що дані не обробляються і що запити також розмежовані подвійними лапками. Чому?

Можливо, ваш код програми виглядає приблизно так:

Поставивши подвійну лапку на початку імені користувача, запит стає

Цей запит правильний (не містить синтаксичних помилок), і під час запуску база даних просто повертає 0.

Однак введення однієї лапки на початку імені користувача перетворює запит на

Цей запит неправильний (він містить синтаксичну помилку через лапки всередині лапок другого рядка, і коли він виконується, база даних видає помилку.

Тепер, коли ми знаємо, що запит розмежовано подвійними лапками, ми можемо написати деякі дані, які змінять запит і змусять програму вважати, що ми ввели дані від зареєстрованого користувача.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Правильне ім’я користувача та пароль.

У цьому випадку запит до бази даних буде приблизно таким:

Цей запит правильний, і при його запуску база даних повертає загальну кількість записів у таблиці, оскільки умова завжди виконується, навіть якщо ім'я користувача та пароль неправильні, оскільки кінцева умова АБО '1' = '1 'завжди правда.

SQL Injection 2 - Дізнайтеся назву полів

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

Наприклад, ми збираємося перевірити, чи ім'я одного з полів "користувач".

Ми могли б зробити щось подібне до того, що було показано в попередньому пункті:

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Помилка запиту.

Відповідь програми - "Помилка запиту", що вказує на відсутність поля під назвою "користувач". У цьому випадку запит до бази даних був приблизно таким:

Іншим можливим записом могло бути наступне:

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Помилка запиту.

Відповідь програми - "Помилка запиту", що вказує на відсутність поля під назвою "користувач". У цьому випадку запит до бази даних був приблизно таким:

У SQL дефіси є позначкою початку коментаря, тому остаточна цитата не враховується у запиті.

В обох випадках ми отримали "Помилка в запиті", тому ми знаємо, що жодне поле не називається "користувачем".

Тепер ми робимо другу спробу з іменем "користувач"

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Неправильне ім’я користувача.

У цьому випадку запит до бази даних буде приблизно таким:

Оскільки ми отримали відповідь "Неправильне ім'я користувача", ми знаємо, що одне з полів називається "користувач".

SQL Injection 3 - з’ясуйте назви таблиць

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

Наприклад, давайте перевіримо, чи назва таблиці "користувачі".

Ми могли б зробити щось подібне до того, що було показано в попередньому пункті:

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Помилка запиту.

Відповідь програми - "Помилка запиту", що говорить нам про відсутність таблиці з назвою "користувачі". У цьому випадку запит до бази даних був приблизно таким:

Тепер ми робимо другу спробу, з назвою "стіл"

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Неправильне ім’я користувача.

У цьому випадку запит до бази даних буде приблизно таким:

Оскільки ми отримали відповідь "Неправильне ім'я користувача", ми знаємо, що одна з таблиць називається "таблиця".

SQL Injection 4 - Дізнайтеся вміст реєстрів

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

Наприклад, давайте шукати імена користувачів.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Правильне ім’я користувача та пароль.

Відповідь програми - "Правильне ім'я користувача та пароль.", Що вказує на наявність користувача, ім'я якого починається на "a". У цьому випадку запит до бази даних був приблизно таким:

Ми могли подовжувати рядок за буквами, поки не знайдемо ім’я користувача.

Введення SQL 5 - Додайте нового користувача

Примітка: Цей тип атаки не працює в прикладі програми в першому розділі цього уроку, оскільки розширення PDO не дозволяє виконувати кілька запитів одночасно, але воно працює в уразливому додатку injection_sql_2.zip, який ви можете перевірити на своєму комп'ютері.

Як тільки ви дізнаєтеся назву таблиці користувачів та назви полів, ви можете спробувати відредагувати базу даних, наприклад, додавши користувача.

Методика полягає у включенні оператора SQL, який вставляє запис.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Неправильне ім’я користувача

У цьому випадку запит до бази даних буде приблизно таким:

Щоб перевірити, чи була атака успішною, спробуйте увійти як "хакерський" користувач із паролем "хакерського".

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

Ін’єкція SQL 6 - Відкиньте таблицю

Примітка: Цей тип атаки не працює в прикладі програми в першому розділі цього уроку, оскільки розширення PDO не дозволяє виконувати кілька запитів одночасно, але воно працює в уразливому додатку injection_sql_2.zip, який ви можете перевірити на своєму комп'ютері.

Після того, як ім'я таблиці користувачів стане відомим, ми збираємось виконати руйнівну дію, наприклад, видалити таблицю користувачів.

Методика полягає у включенні оператора SQL, який вставляє запис.

Для входу в систему введіть своє ім’я користувача та пароль:

Користувач:
Пароль:

Неправильне ім’я користувача

Помилка запиту.

У цьому випадку запит до бази даних буде приблизно таким:

Якщо атака буде успішною, програма напевно перестане працювати, оскільки одна з таблиць зникла.

До кінця .

Чудовий комікс xkcd опублікував жарт на цю тему:

користувача пароль

Цю сторінку востаннє змінено: 29 листопада 2012 р


Ця сторінка є частиною курсу Веб-програмування на PHP від Бартоломе Сінтеса Марко
яка розповсюджується за ліцензією Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).