Така наречените "SQL инжекции" са вид атака срещу приложение, което използва недостатъци на сигурността в базата данни. В този урок ще видим примери за SQL инжекции. Този урок се основава на статията на Steve Friedl SQL Injection Attacks by Example, която препоръчвам да прочетете, или измамническия лист на SQL инжекцията. Разбира се, целта на този урок е да повиши информираността за необходимостта от защита на всяко уеб приложение от този тип атака.

Примерно приложение

Ще използваме като пример приложение, подобно на това в упражненията Бази данни 1.

  • Това приложение има меню с три опции:
    • Изтрийте всичко, да изтриете и създадете потребителската таблица, която съдържа само две полета (име и парола на потребителя).
    • Добавете потребители, за да добавите потребителски имена и техните пароли в потребителската таблица.
    • Влезте в системата, което симулира страница за вход в уеб приложение, изискващо потребителско име и парола, проверка дали е в таблицата на потребителите и отговор
      • потребителското име и паролата са правилни.
      • потребителското име е правилно, но паролата не е правилна.
      • потребителското име не е правилно.
  • Това приложение е уязвимо за някои SQL инжекционни атаки, тъй като данните, изпратени от потребителя, са включени в заявките към базата данни без предварително третиране.
  • Това приложение не е уязвимо за всички атаки на SQL инжектиране, обсъдени в този урок, защото използва разширението PDO. Ако искате да тествате подобно приложение, уязвимо за всички атаки, обсъдени в този урок, на вашия компютър, можете да изтеглите този файл (injection_sql_2.zip) и да го тествате на компютъра си.

SQL Injection 1 - Достъп до приложението без потребителско име или парола

Когато потребителят въведе потребителско име и парола, приложението отговаря на едно от трите съобщения:

За да влезете в системата, въведете потребителското си име и парола:

Потребител:
Парола:

Правилно потребителско име и парола.

Неправилно потребителско име.

За да проверим дали приложението включва данните, изпратени от потребителя без предварително третиране, можем да изпратим оферта (единична или двойна) като данни.

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Неправилно потребителско име.

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Грешка в заявката.

Това последно съобщение („Грешка в заявката“) ни уведомява, че данните не се обработват и че заявките също са разграничени с двойни кавички. Защо?

Вероятно кодът на приложението ви изглежда по следния начин:

Като поставите двойна кавичка в началото на потребителското име, заявката става

Тази заявка е правилна (не съдържа синтаксични грешки) и при изпълнение на базата данни просто връща 0.

Въвеждането на единична кавичка в началото на потребителското име обаче превръща заявката в

Тази заявка не е правилна (съдържа синтаксична грешка поради кавичката вътре в кавичките на втория ред и когато се изпълни, базата данни дава грешка.

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

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Правилно потребителско име и парола.

В този случай заявката за база данни ще бъде нещо подобно:

Тази заявка е правилна и когато се изпълни, базата данни връща общия брой записи в таблицата, тъй като условието винаги е изпълнено, дори ако потребителското име и паролата са неправилни, тъй като крайното условие ИЛИ '1' = '1 винаги е вярно.

SQL инжекция 2 - Разберете името на полетата

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

Например ще тестваме дали името на едно от полетата е „потребител“.

Бихме могли да направим нещо подобно на това, което се вижда в предишната точка:

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Грешка в заявката.

Отговорът на приложението е "Грешка в заявката", което показва, че няма поле, наречено "потребител". В този случай заявката към базата данни ще бъде по следния начин:

Друг възможен запис може да бъде следният:

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Грешка в заявката.

Отговорът на приложението е „Грешка в заявката“, което показва, че няма поле, наречено „потребител“. В този случай заявката към базата данни ще бъде по следния начин:

В SQL тиретата са началната марка на коментар, така че крайната оферта не се взема предвид в заявката.

И в двата случая получихме „Грешка в заявката“, така че знаем, че нито едно поле не се нарича „потребител“.

Сега правим втори опит с името "потребител"

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Неправилно потребителско име.

В този случай заявката за база данни ще бъде нещо подобно:

Тъй като получихме отговора „Лошо потребителско име“, знаем, че едно от полетата се нарича „потребител“.

SQL инжекция 3 - Разберете имената на таблиците

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

Например, нека тестваме дали името на таблицата е „потребители“.

Бихме могли да направим нещо подобно на това, което се вижда в предишната точка:

За да влезете в системата, въведете потребителското си име и парола:

Потребител:
Парола:

Грешка в заявката.

Отговорът на приложението е "Query failed", което ни казва, че няма таблица, наречена "потребители". В този случай заявката към базата данни ще бъде нещо подобно:

Сега правим втори опит, с името "таблица"

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Неправилно потребителско име.

В този случай заявката за база данни ще бъде нещо подобно:

Тъй като получихме отговора „Лошо потребителско име“, знаем, че една от таблиците се нарича „таблица“.

SQL инжекция 4 - Разберете съдържанието на регистрите

След като знаете името на потребителската таблица и имената на полетата, можете да опитате да откриете конкретни стойности на запис чрез проби и грешки. Идеята е да се въведат данни, които изграждат заявки, в които се появява възможно съдържание на полетата. В случай че заявките дават грешка, това означава, че съдържанието е неправилно, ако не, това означава, че сме ударили съдържанието.

Например, нека да търсим потребителски имена.

За да влезете в системата, въведете вашето потребителско име и парола:

Потребител:
Парола:

Правилно потребителско име и парола.

Отговорът от приложението е „Правилно потребителско име и парола.“, Което показва, че има потребител, чието име започва с „а“. В този случай заявката към базата данни ще бъде по следния начин:

Можем да удължаваме низа буква по буква, докато намерим името на потребителя.

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 License (CC BY-SA 4.0).