Closed caramel2312 closed 1 day ago
Назва ПЗ: Tholum Crm42 URL-посилання в інтернеті: https://github.com/tholum/crm42 Призначення програмного забезпечення CRM42 полягає в управлінні взаємовідносинами з клієнтами, зокрема в організації контактів, відстеженні взаємодій та збереженні важливої інформації про клієнтів у зручному форматі. Приклади споживачів, які можуть бути зацікавлені у використанні такого ПЗ:
У програмному забезпеченні tholum crm42 було виявлено критичну вразливість. Вона зачіпає невідомий процес обробки файлу crm42\class\class.user.php у компоненті Login. Маніпуляція аргументом user_name може призвести до SQL-ін'єкції. Атака може бути здійснена дистанційно. Експлойт для цієї вразливості було оприлюднено, і він може бути використаний. Цій вразливості було присвоєно ідентифікатор VDB-213461.
Код не виконує жодної фільтрації вхідних даних, передаючи їх безпосередньо до SQL-запиту:
$sql = "SELECT * FROM users WHERE user_name = '$user_name' AND password = '$password'"; $result = $db->query($sql);
Вхідні дані user_name та password включаються у запит без попередньої обробки (наприклад, екранування спеціальних символів або використання підготовлених виразів). Це дозволяє зловмиснику виконати SQL-ін’єкцію. Як усунути вразливість:
$stmt = $db->prepare("SELECT * FROM users WHERE user_name = ? AND password = ?"); $stmt->bind_param("ss", $user_name, $password); $stmt->execute(); $result = $stmt->get_result();
Вебзастосунки, що використовують контент на основі баз даних, є всюдисущими. Компанії, чия бізнес-модель зосереджена на Інтернеті, такі як Yahoo та Amazon, є очевидними прикладами; однак майже кожна велика компанія має веб-присутність, і ця присутність часто базується на реляційних базах даних. Ці бази даних можуть містити чутливу інформацію, таку як дані клієнтів. Зазвичай користувач вебзастосунку надає інформацію, наприклад, ім'я користувача та пароль, і у відповідь отримує персоналізований контент. Також є поширеною практика надання публічного контенту через зовнішній сайт із одночасним розміщенням інтранету на тому ж вебсервері. Різноманітні технології пропонують фреймворки для вебзастосунків, зокрема J2EE від Sun (Java Server Pages, Servlets, Struts тощо), ASP та ASP.NET від Microsoft, PHP і Common Gateway Interface (CGI). Усі ці моделі використовують багаторівневе середовище. Зазвичай застосовуються три рівні: рівень представлення, проміжний рівень і рівень даних. Рівень представлення використовує веббраузер для отримання введених даних користувача і представлення вихідної інформації. Це зазвичай HTML, хоча іноді для інтранет-застосунків використовуються спеціальні тонкі клієнти. Проміжний рівень, також відомий як бізнес-рівень, інкапсулює бізнес-логіку, яка керує застосунком. Цей програмний шар відповідає за формування запитів до рівня бази даних. Рівень даних зазвичай є реляційною базою даних і надає послуги зберігання.
Як мотивуючий приклад розглянемо вебзастосунок для інтернет-банкінгу. Банк дозволяє клієнтам входити в систему, переглядати рахунки, здійснювати платежі тощо. Клієнти вводять свої облікові дані, наприклад ім’я користувача та пароль, на вебсторінці (рівень представлення). Вебсторінка передає цю інформацію у вигляді пар "ім’я:значення" (поле введення:значення) на проміжний рівень. Проміжний рівень використовує це введення для створення запиту до рівня бази даних. Це майже завжди SQL (мова структурованих запитів), наприклад:
SELECT * FROM users WHERE username='greg' AND password='secret'.
Рівень даних обробляє запит і повертає набір записів назад на проміжний рівень. Проміжний рівень обробляє дані, створює сесію і передає частину даних на рівень представлення. Рівень представлення рендерить інформацію у вигляді HTML для браузера, показуючи меню з опціями рахунку та персоналізовану інформацію про баланси рахунків і історію транзакцій. Зверніть увагу, що у цьому прикладі проміжний рівень генерує SQL-запит на основі введення користувача. Через популярність таких застосунків методи використання їхніх вразливостей можуть бути надзвичайно небезпечними. Одним із таких методів є SQL-ін'єкція. Ця атака відбувається, коли введені користувачем дані інтерпретуються як SQL-токени, змінюючи семантику початкового запиту. Дві відомі компанії, чиї публічні вебсайти були вразливими до таких атак, — Guess і Petco. Обидві вразливості були виявлені цікавим 20-річним програмістом у 2003 році. У результаті Petco розкрив 500 000 номерів кредитних карток, що призвело до врегулювання з Федеральною торговою комісією [18, 21].
У цій роботі ми пропонуємо нову техніку часу виконання для усунення SQL-ін'єкцій. Ми спостерігаємо, що всі SQL-ін'єкції змінюють структуру запиту, яку задумав програміст. Захоплюючи цю структуру під час виконання, ми можемо порівняти її з розібраною структурою після вставлення введених користувачем даних і оцінити їхню схожість. Ми стверджуємо, що ефективніше оцінювати результати введення, ніж намагатися перевіряти його до вставлення у запропонований запит. Використовуючи простий SQL-парсер, ми можемо оцінювати всі введені дані без необхідності звертатися до бази даних, що знижує витрати часу виконання. Наша методика спрямована на досягнення таких трьох критеріїв:
• усунення можливості атаки; • мінімізація зусиль, необхідних від програміста; • мінімізація накладних витрат часу виконання.
Окрім опису структури техніки, ми представляємо реалізацію нашого рішення на прикладі дослідження випадку в J2EE і оцінюємо його на основі цих трьох критеріїв. Ми дійшли висновку, що наше рішення забезпечує практичний і корисний інструмент безпеки для розробників проміжного програмного забезпечення, і робимо код загальнодоступним. Наша загальна стратегія не обмежується жодною конкретною платформою, оскільки вона не залежить від певного мовного механізму чи технології. Цю стратегію можна застосувати до будь-якого існуючого фреймворку вебзастосунків.
SQL-ін'єкції стали об'єктом підвищеної уваги за останні два роки. Хоча ця вразливість існує вже деякий час, нещодавні зусилля хакерів з автоматизації пошуку вразливих сайтів спричинили активізацію винахідництва в науковій спільноті [1, 9, 8, 19]. Промислове співтовариство також доклало зусиль, щоб підвищити обізнаність програмістів і надати найкращі практики для мінімізації проблеми [16, 15, 3, 22, 17]. Offutt та Xu [20] зробили тестування SQL-ін'єкцій ключовим випадком у своїх нещодавніх дослідженнях тестування та верифікації вебслужб. Проте, нещодавнє дослідження показало, що понад 75% вебатак відбуваються на рівні застосунків, а тестування 300 вебсайтів виявило, що 97% із них вразливі до атак на вебзастосунки [21, 10]. Втім, ми вважаємо, що проблема SQL-ін'єкцій є цілком вирішуваною. Вона має схожість із викликами безпеки, пов’язаними з переповненням буфера, оскільки введені користувачем дані виходять за межі їхнього положення у запиті [5, 6]. У центрі цієї проблеми стоїть завдання перевірки того, що користувач не змінив синтаксис запиту. Тому більшість робіт трактують проблему як задачу валідації введених даних і зосереджуються на аналізі рядкових даних [2]. Існує кілька технологій, які допомагають програмістам перевіряти введення. Простий метод полягає у перевірці наявності одинарних лапок та дефісів, а також їхньому ручному екрануванні. Однак цей підхід легко обійти, оскільки зловмисники можуть просто адаптувати своє введення під екрановані символи. Програмістам доводиться перевіряти попередньо екранований текст тощо. У роботі [4] Меллер та Шварцбах використовують двоетапний процес для оцінки можливих рядків, що можуть виникати в операціях на Java. Спочатку вони застосовують графи потоків, а потім використовують ці графи для створення скінчених автоматів, які представляють множину можливих рядків.
Традиційний метод
Connection conn = DriverManager.getConnection(strDBconn); Statement s = conn.createStatement(); String q = ‘‘SELECT * FROM reports WHERE id=’’ + id; ResultSet RS = s.execute(q); ... RS.close(); conn.close();
Захищений метод
Connection conn = SafeDriverManager.getConnection(strDBconn); Statement s = conn.createStatement(); String q = SQLGuard.init() + ’’SELECT * FROM reports WHERE id=’’ + SQLGuard.wrap(id); ResultSet RS = s.execute(q); ... RS.close(); conn.close();
Джерельний код для незмінного SQL-запиту (зверху) та захищеного SQL-запиту (знизу)
Декілька технік використовують підхід статичного аналізу для створення моделей потенційних SQL-запитів [9, 8, 23]. Вассерман і Су [23] застосовують техніку статичного аналізу з [4] для створення скінчених автоматів, які моделюють множину дійсних SQL-команд для кожного доступу до даних. Цей метод надає гарантії щодо поведінки системи і є досить корисним. Проте він має кілька недоліків. Він не підтримує багато запитів, таких як ті, що використовують оператор LIKE. Це обмеження є питанням реалізації, і є підстави вважати, що підтримка наразі не підтримуваних запитів з'явиться у майбутньому. Однак, як і у випадку з будь-яким статичним дизайном, цей підхід погано моделює динамічно згенеровані запити.
Наприклад, пошук, де користувач визначає поля для пошуку, такі як пошук за темою, тілом листа, відправником тощо. Через можливість будь-якої комбінації цих полів статичний аналіз не може визначити остаточну структуру запиту. Крім того, методика запобігання атакам через тавтології є явною та, відповідно, надмірно складною. Вона намагається визначити (за допомогою SQL-токенів), чи є булевий автомат істинним. Кількість випадків для цього аналізу велика; здається, вони пропускають прості булеві випадки, які не використовують математичних операторів.
Нещодавно Халфонд і Орсо поєднали ці техніки статичного аналізу з динамічною верифікацією [10, 11]. Ця робота є найбільш схожою на нашу. Як і у попередньому методі, будь-яка техніка, чия модель створюється під час компіляції, не може передбачити точну структуру запиту. Хуанг та ін. [12] також використовують як статичні, так і динамічні техніки, але вони вимагають, щоб усі чутливі функції мали свої передумови чітко визначені в анотаціях (політиках довіри).
Бойд і Керемітіс [1, 13] розробили SQLRand — техніку, що змінює токени мови SQL: кожен тип токена включає доданий префікс у вигляді цілого числа. Будь-який додатковий SQL, наданий користувачем, наприклад, OR 1=1, не буде співпадати з розширеними токенами SQL, що призведе до виникнення помилки. Цей підхід є корисною стратегією і може ефективно усунути SQL-ін'єкції. Однак з практичної точки зору програмісту потрібно створити інтерфейс між рівнем бази даних і середнім рівнем, який може генерувати і враховувати нові токени. Це не є тривіальним завданням. По-друге, і що важливіше, ці нові токени є статичними. Як було зазначено авторами, багато додатків експортують помилки SQL [14], тому ці нові токени можуть бути відкрито доступними. Зовнішнє знання про нові токени знижує ефективність цієї техніки.
PHP5 має технологію під назвою Magic Quotes, яка автоматично екранує введення з об'єкта Request. Ця функція викликала труднощі у програмістів, оскільки це налаштування сервера, і додатки часто пишуться, припускаючи, що воно включене або вимкнене, що призводить до неправильних припущень, а отже — до недійсних або двічі екранованих введень. Спроби полегшити фрустрацію програмістів, такі як надання API для перевірки налаштування під час виконання, дали змішані результати.
Кілька комерційних платформ впровадили строгий типізований підхід для допомоги програмістам у боротьбі з SQL-ін'єкціями. J2EE має підготовлені запити, а в Microsoft .NET є команди. Ефективність підготовлених запитів у запобіганні SQL-ін'єкціям залежить від їх реалізації, яка знаходиться в драйверах баз даних і зазвичай написана сторонніми постачальниками. Оскільки підготовлені запити були спочатку створені для виконання кількох запитів на одному виразі, вони не дуже зручні у використанні. Кожен параметр повинен бути попередньо приведений до правильного типу користувачем і заданий окремими рядками коду. Крім того, для формулювання моделі необхідно зробити два запити до бази даних. Нарешті, багато платформ не підтримують технології зі строгим типізуванням.
Окрім усунення SQL-ін'єкцій, ми вважаємо, що життєздатне рішення не повинно ускладнювати роботу програміста. Головна причина, чому запити пишуться як динамічно згенеровані рядки (на відміну від підготовлених запитів), полягає у зручності використання. Наш підхід поєднує переваги обох підходів: зручність динамічно згенерованих рядків і безпеку підготовлених запитів.
5
Варіант 29