logo

SQL инжекция

SQL инжектирането е пропуск в сигурността на уеб приложенията, при който нападателите вмъкват вреден SQL код чрез въвеждане от потребителя. Това може да им позволи достъп до чувствителни данни, да променят съдържанието на базата данни или дори да поемат контрол над системата. Важно е да знаете за SQL Injection, за да запазите сигурността на уеб приложенията.

SQL Injection (SQLi) е уязвимост в сигурността, която възниква, когато хакер може да манипулира заявките към базата данни на уеб приложение чрез вмъкване на злонамерен SQL код в полетата за въвеждане от потребителя. Тези инжектирани заявки могат да манипулират основната база данни, за да извлекат модифицирани или изтрити чувствителни данни. В някои случаи нападателите могат дори да ескалират привилегиите, за да получат пълен контрол върху базата данни или сървъра.



sql инжекция' title=

Пример от реалния свят:

През 2019 г. се случи нарушение на данните на Capital One поради неправилно конфигурирано уеб приложение, което позволи на атакуващ да използва уязвимост при инжектиране на SQL. Това доведе до изтичане на лични данни на над 100 милиона клиенти, включително имена, адреси и кредитни рейтинги.

Ниво на сигурност на SQL инжектиране

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';';

Как може да бъде атака:



Едно просто'инжекцията вече няма да работи (защото става').

Но нападателите все още могат да заобиколят чрез цифрово инжектиране (тъй като числата не се нуждаят от кавички).
Пример:

arraylist.sort
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 инжектиране

1. Базирано на грешки SQL инжектиране

Базираното на грешки SQL инжектиране е тип вътрешнолентово SQL инжектиране, при което атакуващият умишлено кара базата данни да генерира съобщение за грешка. След това атакуващият анализира това съобщение за грешка, за да получи ценна информация за структурата на базата данни, като имена на таблици и имена на колони, които могат да се използват за създаване на допълнителни по-прецизни атаки.

Как работи

Тази атака е насочена към приложения, които разкриват необработени грешки в базата данни, вместо да показват общи съобщения. Чрез инжектиране на злонамерен вход, който нарушава SQL синтаксиса, нападателите задействат тези грешки и получават ценни улики за структурата на базата данни.

низ в масив c
  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 Сигурност и задайте ниско ниво на защита. Това ще гарантира, че уязвимостите са лесни за използване.
файл' loading='lazy' title=

Стъпка 2: Идентифицирайте уязвимостта

Страницата за SQL инжектиране има просто поле за въвеждане, където можете да въведете потребителско име. Заявката за задната част вероятно е нещо подобноSELECT * FROM users WHERE id = 'user_input'

  • Въведете валиден ID като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 = ''';

Тук базата данни вижда допълнителен цитат и не знае как да завърши заявката.

иначе ако bash

Вместо да ви покаже подробностите за потребителя, приложението ще върне SQL грешка (нещо като „Имате грешка във вашия SQL синтаксис…“)

Това се нарича базирано на грешки SQL инжектиране, защото:

  • Нападателят изпраща невалиден вход (')
  • Базата данни извежда грешка
  • Тази грешка изтича полезна информация за базата данни (като тип DB брой колони структура и т.н.)

2. Базирано на съюз SQL инжектиране

Базираното на съюза SQL инжектиране е техника, при която нападателите използватUNIONоператор за комбиниране на резултатите от две или повечеSELECTизявления в един резултатен набор. Това може да им позволи да извличат информация от други таблици в базата данни. TheUNIONоператор може да се използва само ако:

  • И двете заявки имат еднакъв брой колони
  • Колоните имат подобни типове данни
  • Колоните са в същия ред

Оператор UNION : TheUNIONсе използва за комбиниране на набор от резултати от два или повечеSELECTизявления.

  • всекиSELECTизявление в рамките наUNIONтрябва да има същия брой колони
  • Колоните трябва да имат подобни типове данни
  • Колоните трябва да са в еднакъв ред
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Пример:

Стъпка 1: Първо трябва да намерим броя на колоните на съществуващата таблица в уебсайта, за да инжектираме базирано на UNION SQL инжектиране:

Страницата за SQL инжектиране има просто поле за въвеждане, където можете да въведете потребителско име. Заявката за задната част вероятно е нещо подобно

 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клауза

команда arp-a
  • Опитайте се да сортирате резултатите по колони
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е а вярно изявление.

как да изтеглите играта pigeon на android
user_input = 'admin' AND 1=2; --

Ако страницата показва грешка или се държи различно, нападателят знае това1=2е а невярно изявление.

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

Използвайки поредица от тези верни/неверни въпроси, нападателят може систематично да отгатва и извлича информация един знак наведнъж. Процесът може да бъде автоматизиран, за да познае всичко - от имена на таблици до потребителски пароли.

Въздействие на SQL Injection Attacks

  • Неоторизиран достъп до чувствителни данни : Нападателите могат да извлекат лична финансова или поверителна информация, съхранявана в базата данни.
  • Проблеми с целостта на данните : Нападателите могат да променят изтриват или повредят критични данни, засягащи функционалността на приложението.
  • Ескалация на привилегии : Нападателите могат да заобиколят механизмите за удостоверяване и да получат административни привилегии.
  • Престой на услугата : 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. Обработка на грешки

Конфигурирайте базата данни и приложението да не показват подробни съобщения за грешка на потребителя. Вместо това регистрирайте грешките вътрешно и показвайте общи съобщения за грешка на крайните потребители.