SQL ін'єкція — це простий вектор атаки, який досі дуже поширений. Причина цього — відсутність патчу для дурниць. Чому ви так кажете? Візьмемо JAVA як приклад:
Припустимо, у базі даних існує така таблиця:
Потім використовуйте таблицю дій JDBC:
Вищезазначений код часто використовують деякі розробники. Уявіть ситуацію, коли вхідний параметр userId — «3; user drop table; Виконується SQL-оператор такий:
Після компіляції та виконання бази даних таблиця користувача видаляється. Вуаля, спрацьовує проста атака SQL-ін'єкції! Це пов'язано з тим, що наведений вище код не відповідає специфікаціям програмування.
Коли ми програмуємо відповідно до специфікації, SQL-ін'єкції взагалі відсутні. Це також такПерший спосіб уникнути SQL-ін'єкції: попередньо скомпільовані оператори, код виглядає так:
Чому в наведеному вище коді немає SQL ін'єкції? Оскільки використовується попередньо скомпільований оператор, попередньо скомпільований оператор встановлює «вибрати ім'я з користувача, де id=?» Оператор компілюється заздалегідь, щоб його замінювали на вхідні параметри лише при виконанні? Заповнювачі — це нормально. У першому випадку несумісності програма пише SQL-оператор, а потім компілює його з вмістом, переданим користувачем, і саме це є проблемою.
Окрім використання попередньо скомпільованих операторів, існує другий варіантСпособи уникнути атак SQL-ін'єкцій: Збережені процедури。 Збережена процедура — це набір SQL-операторів, які виконують певну функцію, скомпільовані та збережені в базі даних, і користувач може виконати її, викликаючи збережену процедуру та надаючи параметр (якщо збережена процедура має параметри), що також дозволяє уникнути атак SQL-ін'єкцій
Відповідна процедура збереження у наведеному вище коді виглядає так:
Звісно, користувачі також можуть перевіряти символи на фронтенді, що також є способом уникнути SQL-ін'єкції: наприклад, для параметра userId вище користувач перевірить крапку з комою, і з'явиться помилка. Однак найфундаментальніша причина полягає в тому, що атаки SQL-ін'єкцій існують через те, що додатки не використовують найменші привілеї при доступі до баз даних. Схоже, що всі використовують root-акаунт для доступу до бази даних.
Отже, як MyBatis уникає атак SQL-ін'єкцій? Або візьмемо приклад користувача таблиці вище: Припустимо, файл mapper виглядає:
Відповідні java-файли:
Ви можете побачити, що вхідний параметр — userId типу String, коли ми передаємо userId="34; user drop table; Після цього надрукована заява звучить так:
Незалежно від введення userID, його sql-оператор виглядає так. Це пов'язано з тим, що mybatis використовує попередньо скомпільовані оператори в базовій реалізації. Коли база даних виконує цей оператор, вона безпосередньо використовує попередньо скомпільований оператор, а потім замінює заповнювач на пропускаючий userId? Просто йди біжи. Спочатку замінити заповнювачі? Процес компіляції виконується, тому немає місця для виживання SQL-ін'єкції.
То як MyBatis виконує прекомпіляцію SQL? Насправді, клас PreparedStatement використовується внизу фреймворку. Клас PreparedStaement не лише уникає SQL-ін'єкції, а й економить час компіляції (N-1), коли одна й та сама SQL-оператор виконується N разів, що підвищує ефективність.
Якщо змінити вищезазначене твердження на:
Коли ми вводимо userId="34; user drop table; Після цього надрукована заява звучить так:
На даний момент mybatis не використовує попередньо скомпільовані оператори, він спочатку зшиває рядки, а потім компілюється, що саме так працює SQL ін'єкція.
Тому при написанні операторів відображення mybatis намагайтеся використовувати формат "#{xxx}". Якщо потрібно використовувати параметри на кшталт "${xxx}", потрібно фільтрувати їх вручну, щоб запобігти атакам SQL-ін'єкцій.
|