logo

SQL ін'єкція

SQL Injection — це недолік безпеки у веб-додатках, коли зловмисники вставляють шкідливий код SQL через введення користувача. Це може дозволити їм отримати доступ до конфіденційних даних, змінити вміст бази даних або навіть взяти під контроль систему. Важливо знати про SQL Injection для забезпечення безпеки веб-додатків.

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



ін'єкція sql' title=

Реальний приклад:

У 2019 році Capital One Data Breach стався через неправильно налаштований веб-додаток, який дозволив зловмиснику використати вразливість SQL-ін’єкції. Це призвело до витоку особистих даних понад 100 мільйонів клієнтів, включаючи імена, адреси та кредитні рейтинги.

Рівень безпеки SQL Injection

DVWA надає чотири рівні безпеки для SQL Injection, щоб допомогти учням побачити, як різні засоби захисту впливають на атаки:



1. Низький рівень безпеки

Додаток приймає ваші дані та безпосередньо поміщає їх у SQL-запит без фільтрації.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Вхід ': Порушує запит і змушує базу даних видавати помилку, показуючи, що вона вразлива.
  • Вхід 1' OR '1'='1: Обманом робить запит завжди істинним, щоб повертати всіх користувачів.
  • Вхід 1' UNION SELECT user password FROM users--: Приєднується до іншого запиту для отримання прихованих даних, таких як імена користувачів і паролі.

2. Середній рівень безпеки

Додаток застосовує базову дезінфекцію введення за допомогою таких функцій, якaddslashes()втекти'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

Як можна атакувати:



Простий'ін’єкція більше не працюватиме (оскільки вона стає').

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

підключитися до бази даних java
1 OR 1=1

Це все одно повертає всі записи.

3. Високий рівень безпеки

Додаток використовує підготовлені оператори (параметризовані запити) для безпечної обробки введених користувачем даних.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

Атака:

Спроби схожі' OR 1=1абоUNION SELECTбільше не працює.

Запит розглядає всі вхідні дані як дані, а не як код SQL.

Типи SQL ін'єкції

Існують різні типи SQL Injection

1. Впровадження SQL на основі помилок

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

Як це працює

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

методи списку java
  1. Визначте вразливий вхід: Зловмисник знаходить поле введення, як-от панель пошуку або параметр URL-адреси, які безпосередньо взаємодіють із базою даних без належної обробки вхідних даних.
  2. Ввести зловмисне корисне навантаження: Зловмисник вводить спеціальний символ (як одинарні лапки') або функція, яка, як відомо, спричиняє помилку бази даних.
  3. Проаналізуйте помилку: База даних, яка не може обробити неправильний запит, повертає детальне повідомлення про помилку. Це повідомлення може розкривати важливу інформацію, таку як:
    • Система бази даних (наприклад, MySQL Oracle SQL Server).
    • Версія бази даних.
    • Виконується повний SQL-запит.
    • Специфічні синтаксичні помилки, які можна використовувати для розуміння імен таблиць або стовпців.
  4. Уточніть атаку: Використовуючи інформацію, зібрану з повідомлення про помилку, зловмисник може вдосконалити своє корисне навантаження, щоб отримати більше даних, таких як імена користувачів і паролі.

приклад:

Крок 1. Налаштуйте своє середовище

  • Запустіть DVWA. Зазвичай доступ до нього здійснюється шляхом переходу за URL-адресою на зразокhttp://localhost/dvwaу вашому браузері.
файл' loading='lazy' title=
  • Увійдіть до DVWA за допомогою облікових даних за замовчуванням:admin/password.
файл' loading='lazy' title=
  • Перейдіть на вкладку DVWA Security і встановіть низький рівень безпеки. Це забезпечить легкість використання вразливостей.
файл' loading='lazy' title=

Крок 2: Визначте вразливість

Сторінка SQL Injection має просте поле введення, де можна ввести ідентифікатор користувача. Швидше за все, серверний запит виглядає приблизно такSELECT * FROM users WHERE id = 'user_input'

  • Введіть дійсний ідентифікатор, наприклад1у поле введення та натисніть «Надіслати». Ви повинні побачити деталі користувача з ID 1.
файл' loading='lazy' title=

Джерело впровадження SQL

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • Тепер спробуйте розірвати запит. Введіть одну лапку'у полі введення та надішліть.
файл' loading='lazy' title=

Запит виглядає так:

SELECT * FROM users WHERE id = ''';

Тут база даних бачить додаткову цитату і не знає, як виконати запит.

що таке myspace

Замість того, щоб показати вам інформацію про користувача, програма поверне помилку SQL (щось на кшталт «У вас є помилка в синтаксисі SQL…»)

Це називається ін’єкцією SQL на основі помилок, оскільки:

  • Зловмисник надсилає недійсні дані (')
  • База даних видає помилку
  • Через цю помилку витікає корисна інформація про базу даних (наприклад, тип БД, кількість стовпців, структура структури тощо)

2. Впровадження SQL на основі об’єднання

SQL-ін’єкція на основі об’єднання – це техніка, за допомогою якої зловмисники використовуютьUNIONоператор для об’єднання результатів двох або більшеSELECTоператори в єдиний набір результатів. Це може дозволити їм отримувати інформацію з інших таблиць у базі даних. TheUNIONоператор можна використовувати лише якщо:

  • Обидва запити мають однакову кількість стовпців
  • Стовпці мають подібні типи даних
  • Стовпці розташовані в тому ж порядку

Оператор UNION : TheUNIONоператор використовується для об’єднання набору результатів із двох або більшеSELECTзаяви.

  • КоженSELECTтвердження в межахUNIONмає мати однакову кількість стовпців
  • Стовпці повинні мати подібні типи даних
  • Стовпці повинні бути в одному порядку
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

приклад:

крок 1: По-перше, нам потрібно знайти кількість стовпців існуючої таблиці на веб-сайті для впровадження SQL-ін’єкції на основі UNION:

Сторінка SQL Injection має просте поле введення, де можна ввести ідентифікатор користувача. Швидше за все, серверний запит виглядає приблизно так

 SELECT * FROM users WHERE id = 'user_input'

Тепер спробуйте розірвати запит. Введіть одну лапку'у полі введення та надішліть.

Якщо програма вразлива, ви отримаєте детальне повідомлення про помилку. Це може виглядати приблизно так:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

Крок 2: ВикористовуйтеUNIONКлючове слово для визначення кількості стовпців

Для використанняUNIONключове слово (звичайний наступний крок), вам потрібно знати кількість стовпців у вихідному запиті. Це можна дізнатися за допомогоюORDER BYпункт

назва міста в США
  • Спробуйте відсортувати результати за стовпцями
1: 1 ORDER BY 1. 
  • Надіслати. Це повинно працювати.
файл' loading='lazy' title=

Джерело впровадження SQL

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • Збільшити число:
 1 ORDER BY 2. 

Надіслати. Це повинно працювати.

файл' loading='lazy' title=
  • Продовжуйте збільшувати, доки не з’явиться помилка. Наприклад1 ORDER BY 4може дати вам:Unknown column '4' in 'order clause'
  • Це означає, що запит має 3 стовпці.

3. Сліпе впровадження SQL

Сліпе впровадження SQL виникає, коли зловмисники не можуть побачити результати запиту безпосередньо на веб-сторінці. Натомість вони виводять інформацію з незначних змін у поведінці програми або часу відповіді. Хоча він повільніший і трудомісткіший, ніж класичний SQLi, він може бути однаково ефективним.

Замість того, щоб отримати дані назад, зловмисник отримує інформацію, спостерігаючи за поведінкою веб-сторінки. Зазвичай це робиться одним із двох способів:

  1. Сліпий SQLi на основі логічних значень: Зловмисник вводить SQL-запит, який повертає a правда або помилковий результат. Відповідь веб-програми змінюється залежно від того, правдивий чи хибний запит. Наприклад, сторінка може відображати інше повідомлення або відображати інший макет.
  2. Сліпий SQLi на основі часу: Зловмисник вводить SQL-запит, який змушує базу даних виконувати трудомістку дію (наприклад,SLEEP()функція), якщо виконується умова. Зловмисник спостерігає за часом, потрібним для завантаження сторінки, щоб визначити, чи була введена умова істинною чи хибною.

приклад:

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

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

Сліпе впровадження SQL передбачатиме маніпулюванняuser_inputполе, щоб поставити запитання базі даних.

Замість отримання прямої відповіді зловмисник може спробувати щось на зразок цього:

user_input = 'admin' AND 1=1; --

Якщо сторінка завантажується нормально, зловмисник це знає1=1є a правда заява.

паліндром в java
user_input = 'admin' AND 1=2; --

Якщо сторінка показує помилку або поводиться інакше, зловмисник це знає1=2є a помилковий заява.

файл' loading='lazy' title=

Використовуючи серію цих запитань «правда/неправда», зловмисник може систематично вгадувати та витягувати інформацію по одному символу за раз. Процес можна автоматизувати, щоб вгадувати все, від імен таблиць до паролів користувачів.

Вплив атак SQL Injection

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

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

Існує кілька найкращих методів запобігання атакам SQL-ін’єкції:

1. Використовуйте підготовлені оператори та параметризовані запити

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

Приклад у PHP (з використанням MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. Використовуйте збережені процедури

Збережені процедури — це попередньо визначені запити SQL, які зберігаються в базі даних. Ці процедури можуть допомогти запобігти впровадження SQL, оскільки вони не створюють динамічно запити SQL.

приклад:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. Перевірка введених даних у білому списку

Переконайтеся, що введені користувачем дані перевірені перед використанням у запитах SQL. Дозволяйте лише певні символи та шаблони, як-от буквено-цифровий ввід, для таких полів, як імена користувачів або адреси електронної пошти.

4. Використовуйте ORM Frameworks

Структури об’єктно-реляційного відображення (ORM), як сплячий режим або Entity Framework може допомогти запобігти ін'єкції SQL, автоматично обробляючи генерацію запиту, запобігаючи динамічному створенню запиту.

5. Обмежте привілеї бази даних

Надайте користувачам мінімально необхідні дозволи на базу даних. Переконайтеся, що програми можуть виконувати лише необхідні дії (наприклад, SELECT INSERT) і обмежте такі дозволи, як DROP TABLE або ALTER.

6. Обробка помилок

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